PKG_NAME:=mac80211
-PKG_VERSION:=6.16
+PKG_VERSION:=6.18
PKG_RELEASE:=1
PKG_LICENSE:=GPL-2.0-only
PKG_LICENSE_FILES:=COPYING
-PKG_SOURCE_URL:=@OPENWRT
-PKG_HASH:=67f11320509dd18e5e2c58cb81e9f6c7d19b09f5229baa5880ed4dab71c19052
+PKG_SOURCE_URL:=https://github.com/openwrt/backports/releases/download/backports-v$(PKG_VERSION)
+PKG_HASH:=3bd5d84b1e56cf8addff0d1e4bcf06753c51feee88c4d7925fb7b67784529436
-PKG_SOURCE:=backports-$(PKG_VERSION).tar.xz
+PKG_SOURCE:=backports-$(PKG_VERSION).tar.zst
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(if $(BUILD_VARIANT),$(PKG_NAME)-$(BUILD_VARIANT)/)backports-$(PKG_VERSION)
PKG_BUILD_PARALLEL:=1
help
--- a/local-symbols
+++ b/local-symbols
-@@ -90,6 +90,7 @@ ADM8211=
+@@ -91,6 +91,7 @@ ADM8211=
ATH_COMMON=
WLAN_VENDOR_ATH=
ATH_DEBUG=
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
-@@ -3365,6 +3365,8 @@ void regulatory_hint_country_ie(struct w
+@@ -3335,6 +3335,8 @@ void regulatory_hint_country_ie(struct w
enum environment_cap env = ENVIRON_ANY;
struct regulatory_request *request = NULL, *lr;
/* IE len must be evenly divisible by 2 */
if (country_ie_len & 0x01)
return;
-@@ -3614,6 +3616,7 @@ static bool is_wiphy_all_set_reg_flag(en
+@@ -3584,6 +3586,7 @@ static bool is_wiphy_all_set_reg_flag(en
void regulatory_hint_disconnect(void)
{
void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature);
--- a/local-symbols
+++ b/local-symbols
-@@ -150,6 +150,7 @@ ATH10K_DEBUG=
+@@ -151,6 +151,7 @@ ATH10K_DEBUG=
ATH10K_DEBUGFS=
ATH10K_LEDS=
ATH10K_SPECTRAL=
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
-@@ -3546,6 +3546,16 @@ int ath10k_core_register(struct ath10k *
+@@ -3586,6 +3586,16 @@ int ath10k_core_register(struct ath10k *
queue_work(ar->workqueue, &ar->register_work);
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -9951,6 +9951,21 @@ static int ath10k_mac_init_rd(struct ath
+@@ -9970,6 +9970,21 @@ static int ath10k_mac_init_rd(struct ath
return 0;
}
int ath10k_mac_register(struct ath10k *ar)
{
static const u32 cipher_suites[] = {
-@@ -10313,6 +10328,12 @@ int ath10k_mac_register(struct ath10k *a
+@@ -10332,6 +10347,12 @@ int ath10k_mac_register(struct ath10k *a
ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER;
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
-@@ -1315,6 +1315,10 @@ struct ath10k {
+@@ -1320,6 +1320,10 @@ struct ath10k {
s32 tx_power_2g_limit;
s32 tx_power_5g_limit;
};
--- a/drivers/net/wireless/ath/ath10k/leds.c
+++ b/drivers/net/wireless/ath/ath10k/leds.c
-@@ -70,7 +70,7 @@ int ath10k_leds_register(struct ath10k *
+@@ -69,7 +69,7 @@ int ath10k_leds_register(struct ath10k *
ar->leds.cdev.name = ar->leds.label;
ar->leds.cdev.brightness_set_blocking = ath10k_leds_set_brightness_blocking;
if (ret)
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -10329,7 +10329,7 @@ int ath10k_mac_register(struct ath10k *a
+@@ -10348,7 +10348,7 @@ int ath10k_mac_register(struct ath10k *a
ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER;
#ifdef CPTCFG_MAC80211_LEDS
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -1043,6 +1043,40 @@ static inline int ath10k_vdev_delete_syn
+@@ -1052,6 +1052,40 @@ static inline int ath10k_vdev_delete_syn
return 0;
}
static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
{
struct cfg80211_chan_def *chandef = NULL;
-@@ -1075,7 +1109,8 @@ static int ath10k_monitor_vdev_start(str
+@@ -1084,7 +1118,8 @@ static int ath10k_monitor_vdev_start(str
arg.channel.min_power = 0;
arg.channel.max_power = channel->max_power * 2;
arg.channel.max_reg_power = channel->max_reg_power * 2;
reinit_completion(&ar->vdev_setup_done);
reinit_completion(&ar->vdev_delete_done);
-@@ -1521,7 +1556,8 @@ static int ath10k_vdev_start_restart(str
+@@ -1530,7 +1565,8 @@ static int ath10k_vdev_start_restart(str
arg.channel.min_power = 0;
arg.channel.max_power = chandef->chan->max_power * 2;
arg.channel.max_reg_power = chandef->chan->max_reg_power * 2;
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
arg.ssid = arvif->u.ap.ssid;
-@@ -3452,7 +3488,8 @@ static int ath10k_update_channel_list(st
+@@ -3461,7 +3497,8 @@ static int ath10k_update_channel_list(st
ch->min_power = 0;
ch->max_power = channel->max_power * 2;
ch->max_reg_power = channel->max_reg_power * 2;
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
-@@ -9,6 +9,7 @@
+@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/of.h>
#include <linux/property.h>
#include <linux/dmi.h>
#include <linux/ctype.h>
-@@ -3418,6 +3419,8 @@ static int ath10k_core_probe_fw(struct a
+@@ -3458,6 +3459,8 @@ static int ath10k_core_probe_fw(struct a
device_get_mac_address(ar->dev, ar->mac_addr);
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -10121,7 +10121,6 @@ int ath10k_mac_register(struct ath10k *a
+@@ -10140,7 +10140,6 @@ int ath10k_mac_register(struct ath10k *a
ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA);
ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG);
#define HTT_RX_RING_FILL_LEVEL_DUAL_MAC (HTT_RX_RING_SIZE - 1)
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
-@@ -132,7 +132,11 @@ static const struct ce_attr pci_host_ce_
+@@ -133,7 +133,11 @@ static const struct ce_attr pci_host_ce_
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
.src_sz_max = 2048,
.recv_cb = ath10k_pci_htt_htc_rx_cb,
},
-@@ -141,7 +145,11 @@ static const struct ce_attr pci_host_ce_
+@@ -142,7 +146,11 @@ static const struct ce_attr pci_host_ce_
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
.src_sz_max = 2048,
.recv_cb = ath10k_pci_htc_rx_cb,
},
-@@ -168,7 +176,11 @@ static const struct ce_attr pci_host_ce_
+@@ -169,7 +177,11 @@ static const struct ce_attr pci_host_ce_
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
.src_sz_max = 512,
.recv_cb = ath10k_pci_htt_rx_cb,
},
-@@ -193,7 +205,11 @@ static const struct ce_attr pci_host_ce_
+@@ -194,7 +206,11 @@ static const struct ce_attr pci_host_ce_
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
.src_sz_max = 2048,
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -8166,6 +8166,20 @@ static void ath10k_flush(struct ieee8021
+@@ -8180,6 +8180,20 @@ static void ath10k_flush(struct ieee8021
mutex_unlock(&ar->conf_mutex);
}
/* TODO: Implement this function properly
* For now it is needed to reply to Probe Requests in IBSS mode.
* Probably we need this information from FW.
-@@ -9513,6 +9527,7 @@ static const struct ieee80211_ops ath10k
+@@ -9532,6 +9546,7 @@ static const struct ieee80211_ops ath10k
.set_rts_threshold = ath10k_set_rts_threshold,
.set_frag_threshold = ath10k_mac_op_set_frag_threshold,
.flush = ath10k_flush,
.tx_last_beacon = ath10k_tx_last_beacon,
.set_antenna = ath10k_set_antenna,
.get_antenna = ath10k_get_antenna,
-@@ -10334,6 +10349,9 @@ int ath10k_mac_register(struct ath10k *a
+@@ -10353,6 +10368,9 @@ int ath10k_mac_register(struct ath10k *a
if (!ar->hw_params.hw_ops->set_coverage_class)
ar->ops->set_coverage_class = NULL;
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
-@@ -2041,6 +2041,7 @@ static int ath11k_qmi_assign_target_mem_
- struct device_node *hremote_node = NULL;
- struct resource res;
+@@ -2042,6 +2042,7 @@ static int ath11k_qmi_assign_target_mem_
+ struct device *dev = ab->dev;
+ struct resource res = {};
u32 host_ddr_sz;
+ u32 addr;
int i, idx, ret;
for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) {
-@@ -2080,7 +2081,9 @@ static int ath11k_qmi_assign_target_mem_
+@@ -2073,7 +2074,9 @@ static int ath11k_qmi_assign_target_mem_
idx++;
break;
case BDF_MEM_REGION_TYPE:
ab->qmi.target_mem[idx].iaddr = NULL;
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
-@@ -2102,8 +2105,9 @@ static int ath11k_qmi_assign_target_mem_
+@@ -2095,8 +2098,9 @@ static int ath11k_qmi_assign_target_mem_
if (!ab->qmi.target_mem[idx].iaddr)
return -EIO;
} else {
ab->qmi.target_mem[idx].iaddr = NULL;
}
} else {
-@@ -2309,6 +2313,7 @@ static int ath11k_qmi_load_file_target_m
+@@ -2302,6 +2306,7 @@ static int ath11k_qmi_load_file_target_m
struct qmi_wlanfw_bdf_download_resp_msg_v01 resp;
struct qmi_txn txn;
const u8 *temp = data;
void __iomem *bdf_addr = NULL;
int ret = 0;
u32 remaining = len;
-@@ -2320,7 +2325,9 @@ static int ath11k_qmi_load_file_target_m
+@@ -2313,7 +2318,9 @@ static int ath11k_qmi_load_file_target_m
memset(&resp, 0, sizeof(resp));
if (ab->hw_params.fixed_bdf_addr) {
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
-@@ -8248,6 +8248,23 @@ static void ath11k_mac_op_flush(struct i
+@@ -8330,6 +8330,23 @@ static void ath11k_mac_op_flush(struct i
ath11k_mac_flush_tx_complete(ar);
}
static bool
ath11k_mac_has_single_legacy_rate(struct ath11k *ar,
enum nl80211_band band,
-@@ -9823,6 +9840,7 @@ static const struct ieee80211_ops ath11k
+@@ -9920,6 +9937,7 @@ static const struct ieee80211_ops ath11k
.set_bitrate_mask = ath11k_mac_op_set_bitrate_mask,
.get_survey = ath11k_mac_op_get_survey,
.flush = ath11k_mac_op_flush,
int ath11k_thermal_set_throttling(struct ath11k *ar, u32 throttle_state);
--- a/local-symbols
+++ b/local-symbols
-@@ -162,6 +162,7 @@ ATH11K_DEBUG=
+@@ -163,6 +163,7 @@ ATH11K_DEBUG=
ATH11K_DEBUGFS=
ATH11K_TRACING=
ATH11K_SPECTRAL=
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
-@@ -37,7 +37,7 @@ bool ath11k_ftm_mode;
+@@ -39,7 +39,7 @@ bool ath11k_ftm_mode;
module_param_named(ftm_mode, ath11k_ftm_mode, bool, 0444);
MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode");
{
.hw_rev = ATH11K_HW_IPQ8074,
.name = "ipq8074 hw2.0",
-@@ -2481,7 +2481,8 @@ static void ath11k_core_reset(struct wor
+@@ -2521,7 +2521,8 @@ static void ath11k_core_reset(struct wor
static int ath11k_init_hw_params(struct ath11k_base *ab)
{
const struct ath11k_hw_params *hw_params = NULL;
for (i = 0; i < ARRAY_SIZE(ath11k_hw_params); i++) {
hw_params = &ath11k_hw_params[i];
-@@ -2497,7 +2498,31 @@ static int ath11k_init_hw_params(struct
+@@ -2537,7 +2538,31 @@ static int ath11k_init_hw_params(struct
ab->hw_params = *hw_params;
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
-@@ -171,8 +171,8 @@ static struct ath11k_hw_params ath11k_hw
+@@ -173,8 +173,8 @@ static struct ath11k_hw_params ath11k_hw
.supports_shadow_regs = false,
.idle_ps = false,
.supports_sta_ps = false,
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
-@@ -698,8 +698,8 @@ static struct ath11k_hw_params ath11k_hw
+@@ -700,8 +700,8 @@ static struct ath11k_hw_params ath11k_hw
.supports_suspend = false,
.hal_params = &ath11k_hw_hal_params_ipq8074,
.single_pdev_only = false,
if (ce_attr->src_nentries)
--- a/drivers/net/wireless/ath/ath11k/hal.c
+++ b/drivers/net/wireless/ath/ath11k/hal.c
-@@ -1247,20 +1247,16 @@ static int ath11k_hal_srng_create_config
+@@ -1274,20 +1274,16 @@ static int ath11k_hal_srng_create_config
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_HP;
s = &hal->srng_config[HAL_CE_SRC];
s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
-@@ -1268,9 +1264,8 @@ static int ath11k_hal_srng_create_config
+@@ -1295,9 +1291,8 @@ static int ath11k_hal_srng_create_config
s = &hal->srng_config[HAL_CE_DST_STATUS];
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) +
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
-@@ -905,6 +905,67 @@ static struct ath11k_hw_params ath11k_hw
+@@ -907,6 +907,67 @@ static struct ath11k_hw_params ath11k_hw
.support_dual_stations = true,
.pdev_suspend = false,
},
static const struct dmi_system_id ath11k_pm_quirk_table[] = {
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
-@@ -151,6 +151,7 @@ enum ath11k_hw_rev {
+@@ -152,6 +152,7 @@ enum ath11k_hw_rev {
ATH11K_HW_IPQ5018_HW10,
ATH11K_HW_QCA2066_HW21,
ATH11K_HW_QCA6698AQ_HW21,
---
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
-@@ -918,6 +918,7 @@ static struct ath11k_hw_params ath11k_hw
+@@ -920,6 +920,7 @@ static struct ath11k_hw_params ath11k_hw
.bdf_addr = 0x4D200000,
.hw_ops = &ipq5018_ops,
.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),
---
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
-@@ -917,6 +917,7 @@ static struct ath11k_hw_params ath11k_hw
+@@ -919,6 +919,7 @@ static struct ath11k_hw_params ath11k_hw
.max_radios = MAX_RADIOS_5018,
.bdf_addr = 0x4D200000,
.hw_ops = &ipq5018_ops,
static int ath11k_core_get_rproc(struct ath11k_base *ab)
{
struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
-@@ -1144,6 +1174,10 @@ static int ath11k_ahb_probe(struct platf
+@@ -1133,6 +1163,10 @@ static int ath11k_ahb_probe(struct platf
hif_ops = &ath11k_ahb_hif_ops_wcn6750;
pci_ops = &ath11k_ahb_pci_ops_wcn6750;
break;
#endif /* _HIF_H_ */
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
-@@ -2201,6 +2201,8 @@ static int ath11k_qmi_request_device_inf
+@@ -2194,6 +2194,8 @@ static int ath11k_qmi_request_device_inf
if (!ab->hw_params.ce_remap)
ab->mem_ce = ab->mem;
}
static void ath11k_ahb_free_ext_irq(struct ath11k_base *ab)
-@@ -1118,6 +1119,27 @@ err_unregister:
+@@ -1107,6 +1108,27 @@ err_unregister:
return ret;
}
static int ath11k_ahb_fw_resource_deinit(struct ath11k_base *ab)
{
struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
-@@ -1159,7 +1181,7 @@ static int ath11k_ahb_probe(struct platf
+@@ -1148,7 +1170,7 @@ static int ath11k_ahb_probe(struct platf
const struct ath11k_hif_ops *hif_ops;
const struct ath11k_pci_ops *pci_ops;
enum ath11k_hw_rev hw_rev;
hw_rev = (uintptr_t)device_get_match_data(&pdev->dev);
-@@ -1183,6 +1205,7 @@ static int ath11k_ahb_probe(struct platf
+@@ -1172,6 +1194,7 @@ static int ath11k_ahb_probe(struct platf
return -EOPNOTSUPP;
}
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (ret) {
dev_err(&pdev->dev, "failed to set 32-bit consistent dma\n");
-@@ -1199,6 +1222,7 @@ static int ath11k_ahb_probe(struct platf
+@@ -1188,6 +1211,7 @@ static int ath11k_ahb_probe(struct platf
ab->hif.ops = hif_ops;
ab->pdev = pdev;
ab->hw_rev = hw_rev;
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
-@@ -47,6 +47,9 @@
+@@ -48,6 +48,9 @@
#define ATH11K_INVALID_HW_MAC_ID 0xFF
#define ATH11K_CONNECTION_LOSS_HZ (3 * HZ)
/* SMBIOS type containing Board Data File Name Extension */
#define ATH11K_SMBIOS_BDF_EXT_TYPE 0xF8
-@@ -966,6 +969,7 @@ struct ath11k_base {
+@@ -969,6 +972,7 @@ struct ath11k_base {
struct list_head peers;
wait_queue_head_t peer_mapping_wq;
u8 mac_addr[ETH_ALEN];
--- a/drivers/net/wireless/ath/ath11k/pcic.c
+++ b/drivers/net/wireless/ath/ath11k/pcic.c
-@@ -137,6 +137,15 @@ static const struct ath11k_msi_config at
+@@ -139,6 +139,15 @@ static const struct ath11k_msi_config at
},
.hw_rev = ATH11K_HW_QCA6698AQ_HW21,
},
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
-@@ -2118,6 +2118,18 @@ static int ath11k_qmi_assign_target_mem_
+@@ -2111,6 +2111,18 @@ static int ath11k_qmi_assign_target_mem_
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
idx++;
break;
---
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
-@@ -727,6 +727,7 @@ static struct ath11k_hw_params ath11k_hw
+@@ -729,6 +729,7 @@ static struct ath11k_hw_params ath11k_hw
.support_fw_mac_sequence = false,
.support_dual_stations = false,
.pdev_suspend = false,
.name = "qca2066 hw2.1",
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
-@@ -348,12 +348,66 @@ void ath11k_dp_stop_shadow_timers(struct
+@@ -350,12 +350,66 @@ void ath11k_dp_stop_shadow_timers(struct
ath11k_dp_shadow_stop_timer(ab, &ab->dp.reo_cmd_timer);
}
ath11k_dp_srng_cleanup(ab, &dp->wbm_desc_rel_ring);
ath11k_dp_srng_cleanup(ab, &dp->tcl_cmd_ring);
ath11k_dp_srng_cleanup(ab, &dp->tcl_status_ring);
-@@ -375,6 +429,8 @@ static int ath11k_dp_srng_common_setup(s
+@@ -377,6 +431,8 @@ static int ath11k_dp_srng_common_setup(s
int i, ret;
u8 tcl_num, wbm_num;
#endif
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
-@@ -787,6 +787,10 @@ int ath11k_dp_tx_send_reo_cmd(struct ath
+@@ -788,6 +788,10 @@ int ath11k_dp_tx_send_reo_cmd(struct ath
if (cmd_num == 0)
return -EINVAL;
+++ /dev/null
-From 16872194c80f2724472fc207991712895ac8a230 Mon Sep 17 00:00:00 2001
-Date: Thu, 12 Jun 2025 17:45:06 +0900
-Subject: wifi: ath11k: clear initialized flag for deinit-ed srng lists
-
-[ Upstream commit a5b46aa7cf5f05c213316a018e49a8e086efd98e ]
-
-In a number of cases we see kernel panics on resume due
-to ath11k kernel page fault, which happens under the
-following circumstances:
-
-1) First ath11k_hal_dump_srng_stats() call
-
- Last interrupt received for each group:
- ath11k_pci 0000:01:00.0: group_id 0 22511ms before
- ath11k_pci 0000:01:00.0: group_id 1 14440788ms before
- [..]
- ath11k_pci 0000:01:00.0: failed to receive control response completion, polling..
- ath11k_pci 0000:01:00.0: Service connect timeout
- ath11k_pci 0000:01:00.0: failed to connect to HTT: -110
- ath11k_pci 0000:01:00.0: failed to start core: -110
- ath11k_pci 0000:01:00.0: firmware crashed: MHI_CB_EE_RDDM
- ath11k_pci 0000:01:00.0: already resetting count 2
- ath11k_pci 0000:01:00.0: failed to wait wlan mode request (mode 4): -110
- ath11k_pci 0000:01:00.0: qmi failed to send wlan mode off: -110
- ath11k_pci 0000:01:00.0: failed to reconfigure driver on crash recovery
- [..]
-
-2) At this point reconfiguration fails (we have 2 resets) and
- ath11k_core_reconfigure_on_crash() calls ath11k_hal_srng_deinit()
- which destroys srng lists. However, it does not reset per-list
- ->initialized flag.
-
-3) Second ath11k_hal_dump_srng_stats() call sees stale ->initialized
- flag and attempts to dump srng stats:
-
- Last interrupt received for each group:
- ath11k_pci 0000:01:00.0: group_id 0 66785ms before
- ath11k_pci 0000:01:00.0: group_id 1 14485062ms before
- ath11k_pci 0000:01:00.0: group_id 2 14485062ms before
- ath11k_pci 0000:01:00.0: group_id 3 14485062ms before
- ath11k_pci 0000:01:00.0: group_id 4 14780845ms before
- ath11k_pci 0000:01:00.0: group_id 5 14780845ms before
- ath11k_pci 0000:01:00.0: group_id 6 14485062ms before
- ath11k_pci 0000:01:00.0: group_id 7 66814ms before
- ath11k_pci 0000:01:00.0: group_id 8 68997ms before
- ath11k_pci 0000:01:00.0: group_id 9 67588ms before
- ath11k_pci 0000:01:00.0: group_id 10 69511ms before
- BUG: unable to handle page fault for address: ffffa007404eb010
- #PF: supervisor read access in kernel mode
- #PF: error_code(0x0000) - not-present page
- PGD 100000067 P4D 100000067 PUD 10022d067 PMD 100b01067 PTE 0
- Oops: 0000 [#1] PREEMPT SMP NOPTI
- RIP: 0010:ath11k_hal_dump_srng_stats+0x2b4/0x3b0 [ath11k]
- Call Trace:
- <TASK>
- ? __die_body+0xae/0xb0
- ? page_fault_oops+0x381/0x3e0
- ? exc_page_fault+0x69/0xa0
- ? asm_exc_page_fault+0x22/0x30
- ? ath11k_hal_dump_srng_stats+0x2b4/0x3b0 [ath11k (HASH:6cea 4)]
- ath11k_qmi_driver_event_work+0xbd/0x1050 [ath11k (HASH:6cea 4)]
- worker_thread+0x389/0x930
- kthread+0x149/0x170
-
-Clear per-list ->initialized flag in ath11k_hal_srng_deinit().
-
-Fixes: 5118935b1bc2 ("ath11k: dump SRNG stats during FW assert")
----
- drivers/net/wireless/ath/ath11k/hal.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
-(limited to 'drivers/net/wireless/ath/ath11k')
-
---- a/drivers/net/wireless/ath/ath11k/hal.c
-+++ b/drivers/net/wireless/ath/ath11k/hal.c
-@@ -1341,6 +1341,10 @@ EXPORT_SYMBOL(ath11k_hal_srng_init);
- void ath11k_hal_srng_deinit(struct ath11k_base *ab)
- {
- struct ath11k_hal *hal = &ab->hal;
-+ int i;
-+
-+ for (i = 0; i < HAL_SRNG_RING_ID_MAX; i++)
-+ ab->hal.srng_list[i].initialized = 0;
-
- ath11k_hal_unregister_srng_key(ab);
- ath11k_hal_free_cont_rdp(ab);
+++ /dev/null
-From 6bdef22d540258ca06f079f7b6ae100669a19b47 Mon Sep 17 00:00:00 2001
-Date: Tue, 3 Jun 2025 10:25:28 +0800
-Subject: wifi: ath11k: fix sleeping-in-atomic in
- ath11k_mac_op_set_bitrate_mask()
-
-[ Upstream commit 65c12b104cb942d588a1a093acc4537fb3d3b129 ]
-
-ath11k_mac_disable_peer_fixed_rate() is passed as the iterator to
-ieee80211_iterate_stations_atomic(). Note in this case the iterator is
-required to be atomic, however ath11k_mac_disable_peer_fixed_rate() does
-not follow it as it might sleep. Consequently below warning is seen:
-
-BUG: sleeping function called from invalid context at wmi.c:304
-Call Trace:
- <TASK>
- dump_stack_lvl
- __might_resched.cold
- ath11k_wmi_cmd_send
- ath11k_wmi_set_peer_param
- ath11k_mac_disable_peer_fixed_rate
- ieee80211_iterate_stations_atomic
- ath11k_mac_op_set_bitrate_mask.cold
-
-Change to ieee80211_iterate_stations_mtx() to fix this issue.
-
-Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.30
-
-Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices")
-Link: https://patch.msgid.link/20250603-ath11k-use-non-atomic-iterator-v1-1-d75762068d56@quicinc.com
----
- drivers/net/wireless/ath/ath11k/mac.c | 12 ++++++------
- 1 file changed, 6 insertions(+), 6 deletions(-)
-
-(limited to 'drivers/net/wireless/ath/ath11k')
-
---- a/drivers/net/wireless/ath/ath11k/mac.c
-+++ b/drivers/net/wireless/ath/ath11k/mac.c
-@@ -8757,9 +8757,9 @@ ath11k_mac_op_set_bitrate_mask(struct ie
- arvif->vdev_id, ret);
- return ret;
- }
-- ieee80211_iterate_stations_atomic(ar->hw,
-- ath11k_mac_disable_peer_fixed_rate,
-- arvif);
-+ ieee80211_iterate_stations_mtx(ar->hw,
-+ ath11k_mac_disable_peer_fixed_rate,
-+ arvif);
- } else if (ath11k_mac_bitrate_mask_get_single_nss(ar, arvif, band, mask,
- &single_nss)) {
- rate = WMI_FIXED_RATE_NONE;
-@@ -8826,9 +8826,9 @@ ath11k_mac_op_set_bitrate_mask(struct ie
- }
-
- mutex_lock(&ar->conf_mutex);
-- ieee80211_iterate_stations_atomic(ar->hw,
-- ath11k_mac_disable_peer_fixed_rate,
-- arvif);
-+ ieee80211_iterate_stations_mtx(ar->hw,
-+ ath11k_mac_disable_peer_fixed_rate,
-+ arvif);
-
- arvif->bitrate_mask = *mask;
- ieee80211_iterate_stations_atomic(ar->hw,
+++ /dev/null
-From 0f708ced89758247f5d2d70def00e7c1c80ff557 Mon Sep 17 00:00:00 2001
-Date: Wed, 4 Jun 2025 16:34:53 +0200
-Subject: wifi: ath11k: fix dest ring-buffer corruption
-
-commit 8c1ba5091fa9a2d1478da63173b16a701bdf86bb upstream.
-
-Add the missing memory barrier to make sure that destination ring
-descriptors are read after the head pointers to avoid using stale data
-on weakly ordered architectures like aarch64.
-
-The barrier is added to the ath11k_hal_srng_access_begin() helper for
-symmetry with follow-on fixes for source ring buffer corruption which
-will add barriers to ath11k_hal_srng_access_end().
-
-Tested-on: WCN6855 hw2.1 WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.41
-
-Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices")
----
- drivers/net/wireless/ath/ath11k/ce.c | 3 ---
- drivers/net/wireless/ath/ath11k/dp_rx.c | 3 ---
- drivers/net/wireless/ath/ath11k/hal.c | 12 +++++++++++-
- 3 files changed, 11 insertions(+), 7 deletions(-)
-
-(limited to 'drivers/net/wireless/ath/ath11k')
-
---- a/drivers/net/wireless/ath/ath11k/ce.c
-+++ b/drivers/net/wireless/ath/ath11k/ce.c
-@@ -393,9 +393,6 @@ static int ath11k_ce_completed_recv_next
- goto err;
- }
-
-- /* Make sure descriptor is read after the head pointer. */
-- dma_rmb();
--
- *nbytes = ath11k_hal_ce_dst_status_get_length(desc);
-
- *skb = pipe->dest_ring->skb[sw_index];
---- a/drivers/net/wireless/ath/ath11k/dp_rx.c
-+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
-@@ -2650,9 +2650,6 @@ int ath11k_dp_process_rx(struct ath11k_b
- try_again:
- ath11k_hal_srng_access_begin(ab, srng);
-
-- /* Make sure descriptor is read after the head pointer. */
-- dma_rmb();
--
- while (likely(desc =
- (struct hal_reo_dest_ring *)ath11k_hal_srng_dst_get_next_entry(ab,
- srng))) {
---- a/drivers/net/wireless/ath/ath11k/hal.c
-+++ b/drivers/net/wireless/ath/ath11k/hal.c
-@@ -823,13 +823,23 @@ u32 *ath11k_hal_srng_src_peek(struct ath
-
- void ath11k_hal_srng_access_begin(struct ath11k_base *ab, struct hal_srng *srng)
- {
-+ u32 hp;
-+
- lockdep_assert_held(&srng->lock);
-
- if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
- srng->u.src_ring.cached_tp =
- *(volatile u32 *)srng->u.src_ring.tp_addr;
- } else {
-- srng->u.dst_ring.cached_hp = READ_ONCE(*srng->u.dst_ring.hp_addr);
-+ hp = READ_ONCE(*srng->u.dst_ring.hp_addr);
-+
-+ if (hp != srng->u.dst_ring.cached_hp) {
-+ srng->u.dst_ring.cached_hp = hp;
-+ /* Make sure descriptor is read after the head
-+ * pointer.
-+ */
-+ dma_rmb();
-+ }
-
- /* Try to prefetch the next descriptor in the ring */
- if (srng->flags & HAL_SRNG_FLAGS_CACHED)
+++ /dev/null
-From eed5fcf4a3d20fdbd9af2e602eab2b581264822f Mon Sep 17 00:00:00 2001
-Date: Wed, 4 Jun 2025 16:34:56 +0200
-Subject: wifi: ath11k: fix source ring-buffer corruption
-
-commit 6efa0df54022c6c9fd4d294b87622c7fcdc418c8 upstream.
-
-Add the missing memory barrier to make sure that LMAC source ring
-descriptors are written before updating the head pointer to avoid
-passing stale data to the firmware on weakly ordered architectures like
-aarch64.
-
-Note that non-LMAC rings use MMIO write accessors which have the
-required write memory barrier.
-
-Tested-on: WCN6855 hw2.1 WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.41
-
-Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices")
----
- drivers/net/wireless/ath/ath11k/hal.c | 10 +++++++++-
- 1 file changed, 9 insertions(+), 1 deletion(-)
-
-(limited to 'drivers/net/wireless/ath/ath11k')
-
---- a/drivers/net/wireless/ath/ath11k/hal.c
-+++ b/drivers/net/wireless/ath/ath11k/hal.c
-@@ -862,7 +862,11 @@ void ath11k_hal_srng_access_end(struct a
- if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
- srng->u.src_ring.last_tp =
- *(volatile u32 *)srng->u.src_ring.tp_addr;
-- *srng->u.src_ring.hp_addr = srng->u.src_ring.hp;
-+ /* Make sure descriptor is written before updating the
-+ * head pointer.
-+ */
-+ dma_wmb();
-+ WRITE_ONCE(*srng->u.src_ring.hp_addr, srng->u.src_ring.hp);
- } else {
- srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr;
- *srng->u.dst_ring.tp_addr = srng->u.dst_ring.tp;
-@@ -871,6 +875,10 @@ void ath11k_hal_srng_access_end(struct a
- if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
- srng->u.src_ring.last_tp =
- *(volatile u32 *)srng->u.src_ring.tp_addr;
-+ /* Assume implementation use an MMIO write accessor
-+ * which has the required wmb() so that the descriptor
-+ * is written before the updating the head pointer.
-+ */
- ath11k_hif_write32(ab,
- (unsigned long)srng->u.src_ring.hp_addr -
- (unsigned long)ab->mem,
+++ /dev/null
-From 6fc2589aae91818dd1183a589ab97d8e5c25364e Mon Sep 17 00:00:00 2001
-Date: Wed, 4 Jun 2025 16:34:57 +0200
-Subject: wifi: ath11k: fix dest ring-buffer corruption when ring is full
-
-commit aa6956150f820e6a6deba44be325ddfcb5b10f88 upstream.
-
-Add the missing memory barriers to make sure that destination ring
-descriptors are read before updating the tail pointer (and passing
-ownership to the device) to avoid memory corruption on weakly ordered
-architectures like aarch64 when the ring is full.
-
-Tested-on: WCN6855 hw2.1 WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.41
-
-Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices")
----
- drivers/net/wireless/ath/ath11k/hal.c | 11 +++++++++--
- 1 file changed, 9 insertions(+), 2 deletions(-)
-
-(limited to 'drivers/net/wireless/ath/ath11k')
-
---- a/drivers/net/wireless/ath/ath11k/hal.c
-+++ b/drivers/net/wireless/ath/ath11k/hal.c
-@@ -854,7 +854,6 @@ void ath11k_hal_srng_access_end(struct a
- {
- lockdep_assert_held(&srng->lock);
-
-- /* TODO: See if we need a write memory barrier here */
- if (srng->flags & HAL_SRNG_FLAGS_LMAC_RING) {
- /* For LMAC rings, ring pointer updates are done through FW and
- * hence written to a shared memory location that is read by FW
-@@ -869,7 +868,11 @@ void ath11k_hal_srng_access_end(struct a
- WRITE_ONCE(*srng->u.src_ring.hp_addr, srng->u.src_ring.hp);
- } else {
- srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr;
-- *srng->u.dst_ring.tp_addr = srng->u.dst_ring.tp;
-+ /* Make sure descriptor is read before updating the
-+ * tail pointer.
-+ */
-+ dma_mb();
-+ WRITE_ONCE(*srng->u.dst_ring.tp_addr, srng->u.dst_ring.tp);
- }
- } else {
- if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
-@@ -885,6 +888,10 @@ void ath11k_hal_srng_access_end(struct a
- srng->u.src_ring.hp);
- } else {
- srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr;
-+ /* Make sure descriptor is read before updating the
-+ * tail pointer.
-+ */
-+ mb();
- ath11k_hif_write32(ab,
- (unsigned long)srng->u.dst_ring.tp_addr -
- (unsigned long)ab->mem,
+++ /dev/null
-From 9a394fd149502394c20dc2ebecb8acfde6f6aeac Mon Sep 17 00:00:00 2001
-Date: Sun, 10 Aug 2025 22:30:18 +0530
-Subject: wifi: ath11k: fix group data packet drops during rekey
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-[ Upstream commit 97acb0259cc9cbfbd7ab689e25684f3d8ce10e26 ]
-
-During GTK rekey, mac80211 issues a clear key (if the old key exists)
-followed by an install key operation in the same context. This causes
-ath11k to send two WMI commands in quick succession: one to clear the
-old key and another to install the new key in the same slot.
-
-Under certain conditions—especially under high load or time sensitive
-scenarios, firmware may process these commands asynchronously in a way
-that firmware assumes the key is cleared whereas hardware has a valid key.
-This inconsistency between hardware and firmware leads to group addressed
-packet drops. Only setting the same key again can restore a valid key in
-firmware and allow packets to be transmitted.
-
-This issue remained latent because the host's clear key commands were
-not effective in firmware until commit 436a4e886598 ("ath11k: clear the
-keys properly via DISABLE_KEY"). That commit enabled the host to
-explicitly clear group keys, which inadvertently exposed the race.
-
-To mitigate this, restrict group key clearing across all modes (AP, STA,
-MESH). During rekey, the new key can simply be set on top of the previous
-one, avoiding the need for a clear followed by a set.
-
-However, in AP mode specifically, permit group key clearing when no
-stations are associated. This exception supports transitions from secure
-modes (e.g., WPA2/WPA3) to open mode, during which all associated peers
-are removed and the group key is cleared as part of the transition.
-
-Add a per-BSS station counter to track the presence of stations during
-set key operations. Also add a reset_group_keys flag to track the key
-re-installation state and avoid repeated installation of the same key
-when the number of connected stations transitions to non-zero within a
-rekey period.
-
-Additionally, for AP and Mesh modes, when the first station associates,
-reinstall the same group key that was last set. This ensures that the
-firmware recovers from any race that may have occurred during a previous
-key clear when no stations were associated.
-
-This change ensures that key clearing is permitted only when no clients
-are connected, avoiding packet loss while enabling dynamic security mode
-transitions.
-
-Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.9.0.1-02146-QCAHKSWPL_SILICONZ-1
-Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.41
-
-Fixes: 436a4e886598 ("ath11k: clear the keys properly via DISABLE_KEY")
----
- drivers/net/wireless/ath/ath11k/core.h | 2 +
- drivers/net/wireless/ath/ath11k/mac.c | 111 ++++++++++++++++++++++++++++++---
- 2 files changed, 104 insertions(+), 9 deletions(-)
-
-(limited to 'drivers/net/wireless/ath/ath11k')
-
---- a/drivers/net/wireless/ath/ath11k/core.h
-+++ b/drivers/net/wireless/ath/ath11k/core.h
-@@ -414,6 +414,8 @@ struct ath11k_vif {
- bool do_not_send_tmpl;
- struct ath11k_arp_ns_offload arp_ns_offload;
- struct ath11k_rekey_data rekey_data;
-+ u32 num_stations;
-+ bool reinstall_group_keys;
-
- struct ath11k_reg_tpc_power_info reg_tpc_info;
-
---- a/drivers/net/wireless/ath/ath11k/mac.c
-+++ b/drivers/net/wireless/ath/ath11k/mac.c
-@@ -4317,6 +4317,40 @@ static int ath11k_clear_peer_keys(struct
- return first_errno;
- }
-
-+static int ath11k_set_group_keys(struct ath11k_vif *arvif)
-+{
-+ struct ath11k *ar = arvif->ar;
-+ struct ath11k_base *ab = ar->ab;
-+ const u8 *addr = arvif->bssid;
-+ int i, ret, first_errno = 0;
-+ struct ath11k_peer *peer;
-+
-+ spin_lock_bh(&ab->base_lock);
-+ peer = ath11k_peer_find(ab, arvif->vdev_id, addr);
-+ spin_unlock_bh(&ab->base_lock);
-+
-+ if (!peer)
-+ return -ENOENT;
-+
-+ for (i = 0; i < ARRAY_SIZE(peer->keys); i++) {
-+ struct ieee80211_key_conf *key = peer->keys[i];
-+
-+ if (!key || (key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
-+ continue;
-+
-+ ret = ath11k_install_key(arvif, key, SET_KEY, addr,
-+ WMI_KEY_GROUP);
-+ if (ret < 0 && first_errno == 0)
-+ first_errno = ret;
-+
-+ if (ret < 0)
-+ ath11k_warn(ab, "failed to set group key of idx %d for vdev %d: %d\n",
-+ i, arvif->vdev_id, ret);
-+ }
-+
-+ return first_errno;
-+}
-+
- static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
- struct ieee80211_vif *vif, struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key)
-@@ -4326,6 +4360,7 @@ static int ath11k_mac_op_set_key(struct
- struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
- struct ath11k_peer *peer;
- struct ath11k_sta *arsta;
-+ bool is_ap_with_no_sta;
- const u8 *peer_addr;
- int ret = 0;
- u32 flags = 0;
-@@ -4386,16 +4421,57 @@ static int ath11k_mac_op_set_key(struct
- else
- flags |= WMI_KEY_GROUP;
-
-- ret = ath11k_install_key(arvif, key, cmd, peer_addr, flags);
-- if (ret) {
-- ath11k_warn(ab, "ath11k_install_key failed (%d)\n", ret);
-- goto exit;
-- }
-+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
-+ "%s for peer %pM on vdev %d flags 0x%X, type = %d, num_sta %d\n",
-+ cmd == SET_KEY ? "SET_KEY" : "DEL_KEY", peer_addr, arvif->vdev_id,
-+ flags, arvif->vdev_type, arvif->num_stations);
-+
-+ /* Allow group key clearing only in AP mode when no stations are
-+ * associated. There is a known race condition in firmware where
-+ * group addressed packets may be dropped if the key is cleared
-+ * and immediately set again during rekey.
-+ *
-+ * During GTK rekey, mac80211 issues a clear key (if the old key
-+ * exists) followed by an install key operation for same key
-+ * index. This causes ath11k to send two WMI commands in quick
-+ * succession: one to clear the old key and another to install the
-+ * new key in the same slot.
-+ *
-+ * Under certain conditions—especially under high load or time
-+ * sensitive scenarios, firmware may process these commands
-+ * asynchronously in a way that firmware assumes the key is
-+ * cleared whereas hardware has a valid key. This inconsistency
-+ * between hardware and firmware leads to group addressed packet
-+ * drops after rekey.
-+ * Only setting the same key again can restore a valid key in
-+ * firmware and allow packets to be transmitted.
-+ *
-+ * There is a use case where an AP can transition from Secure mode
-+ * to open mode without a vdev restart by just deleting all
-+ * associated peers and clearing key, Hence allow clear key for
-+ * that case alone. Mark arvif->reinstall_group_keys in such cases
-+ * and reinstall the same key when the first peer is added,
-+ * allowing firmware to recover from the race if it had occurred.
-+ */
-
-- ret = ath11k_dp_peer_rx_pn_replay_config(arvif, peer_addr, cmd, key);
-- if (ret) {
-- ath11k_warn(ab, "failed to offload PN replay detection %d\n", ret);
-- goto exit;
-+ is_ap_with_no_sta = (vif->type == NL80211_IFTYPE_AP &&
-+ !arvif->num_stations);
-+ if ((flags & WMI_KEY_PAIRWISE) || cmd == SET_KEY || is_ap_with_no_sta) {
-+ ret = ath11k_install_key(arvif, key, cmd, peer_addr, flags);
-+ if (ret) {
-+ ath11k_warn(ab, "ath11k_install_key failed (%d)\n", ret);
-+ goto exit;
-+ }
-+
-+ ret = ath11k_dp_peer_rx_pn_replay_config(arvif, peer_addr, cmd, key);
-+ if (ret) {
-+ ath11k_warn(ab, "failed to offload PN replay detection %d\n",
-+ ret);
-+ goto exit;
-+ }
-+
-+ if ((flags & WMI_KEY_GROUP) && cmd == SET_KEY && is_ap_with_no_sta)
-+ arvif->reinstall_group_keys = true;
- }
-
- spin_lock_bh(&ab->base_lock);
-@@ -4994,6 +5070,7 @@ static int ath11k_mac_inc_num_stations(s
- return -ENOBUFS;
-
- ar->num_stations++;
-+ arvif->num_stations++;
-
- return 0;
- }
-@@ -5009,6 +5086,7 @@ static void ath11k_mac_dec_num_stations(
- return;
-
- ar->num_stations--;
-+ arvif->num_stations--;
- }
-
- static u32 ath11k_mac_ieee80211_sta_bw_to_wmi(struct ath11k *ar,
-@@ -9553,6 +9631,21 @@ static int ath11k_mac_station_add(struct
- goto exit;
- }
-
-+ /* Driver allows the DEL KEY followed by SET KEY sequence for
-+ * group keys for only when there is no clients associated, if at
-+ * all firmware has entered the race during that window,
-+ * reinstalling the same key when the first sta connects will allow
-+ * firmware to recover from the race.
-+ */
-+ if (arvif->num_stations == 1 && arvif->reinstall_group_keys) {
-+ ath11k_dbg(ab, ATH11K_DBG_MAC, "set group keys on 1st station add for vdev %d\n",
-+ arvif->vdev_id);
-+ ret = ath11k_set_group_keys(arvif);
-+ if (ret)
-+ goto dec_num_station;
-+ arvif->reinstall_group_keys = false;
-+ }
-+
- arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL);
- if (!arsta->rx_stats) {
- ret = -ENOMEM;
+++ /dev/null
-From 888830b2cbc035838bebefe94502976da94332a5 Mon Sep 17 00:00:00 2001
-Date: Wed, 17 Sep 2025 22:20:01 +0300
-Subject: wifi: ath11k: fix NULL dereference in ath11k_qmi_m3_load()
-
-commit 3fd2ef2ae2b5c955584a3bee8e83ae7d7a98f782 upstream.
-
-If ab->fw.m3_data points to data, then fw pointer remains null.
-Further, if m3_mem is not allocated, then fw is dereferenced to be
-passed to ath11k_err function.
-
-Replace fw->size by m3_len.
-
-Found by Linux Verification Center (linuxtesting.org) with SVACE.
-
-Fixes: 7db88b962f06 ("wifi: ath11k: add firmware-2.bin support")
----
- drivers/net/wireless/ath/ath11k/qmi.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-(limited to 'drivers/net/wireless/ath/ath11k')
-
---- a/drivers/net/wireless/ath/ath11k/qmi.c
-+++ b/drivers/net/wireless/ath/ath11k/qmi.c
-@@ -2576,7 +2576,7 @@ static int ath11k_qmi_m3_load(struct ath
- GFP_KERNEL);
- if (!m3_mem->vaddr) {
- ath11k_err(ab, "failed to allocate memory for M3 with size %zu\n",
-- fw->size);
-+ m3_len);
- ret = -ENOMEM;
- goto out;
- }
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
-@@ -2832,6 +2832,9 @@ int ath12k_wmi_send_scan_chan_list_cmd(s
+@@ -2891,6 +2891,9 @@ int ath12k_wmi_send_scan_chan_list_cmd(s
max_chan_limit = (wmi->wmi_ab->max_msg_len[ar->pdev_idx] - len) /
sizeof(*chan_info);
arg->nallchans -= num_send_chans;
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
-@@ -3947,6 +3947,8 @@ struct wmi_stop_scan_cmd {
+@@ -4004,6 +4004,8 @@ struct wmi_stop_scan_cmd {
__le32 pdev_id;
} __packed;
+#define WMI_MAX_NUM_CHAN_PER_WMI_CMD 58
+
struct ath12k_wmi_scan_chan_list_arg {
+ struct list_head list;
u32 pdev_id;
- u16 nallchans;
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
-@@ -6985,9 +6985,7 @@ static void ath12k_mac_setup_ht_vht_cap(
+@@ -7723,9 +7723,7 @@ static void ath12k_mac_setup_ht_vht_cap(
rate_cap_rx_chainmask);
}
+++ /dev/null
-From patchwork Wed May 21 22:45:31 2025
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Id: 14096118
-Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com
- [205.220.180.131])
- (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
- (No client certificate requested)
- by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8D9B523506D
-Authentication-Results: smtp.subspace.kernel.org;
- arc=none smtp.client-ip=205.220.180.131
-ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
- t=1747867559; cv=none;
- b=QXLrpE5trQYq3qZVPuAYdZ8IfmZi7XatjLyxn+9IZXmAWvPsCpT2EOrmLKoTKXH1gxwInwHzxiiwzDveDdYBFh2FGnxhAgdJlTBf1yChfW7+YndhKTtca3rP8z+Zt8QK48/n7gpmFEWkKGmxkG1DKIkCHgAZjD///ttubaAe2gc=
-ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
- s=arc-20240116; t=1747867559; c=relaxed/simple;
- bh=wlnSlGktw4cBYqpNPJwSPfG4fkld5ABcJ0NmmjY/jLg=;
- h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:
- MIME-Version:Content-Type;
- b=A4dIxT87Fh9Y97+jvDIVTPlA5cnixK5ZcCAl5lklS0dCWBpo0QkFFiYyRUSKso7kYaT6KFazofkMt8A2z/fDgN8gVZgqEkaXDFSRjqNWCtoplSK7qYryl88snzbQvzD52CbWKkX8yu2Qmd98HFrl2kg69o1e4wzXVcNc+fehea8=
-ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
- dmarc=pass (p=none dis=none) header.from=quicinc.com;
- spf=pass smtp.mailfrom=quicinc.com;
- header.b=gwsO0461; arc=none smtp.client-ip=205.220.180.131
-Authentication-Results: smtp.subspace.kernel.org;
- dmarc=pass (p=none dis=none) header.from=quicinc.com
-Authentication-Results: smtp.subspace.kernel.org;
- spf=pass smtp.mailfrom=quicinc.com
-Authentication-Results: smtp.subspace.kernel.org;
- header.b="gwsO0461"
-Received: from pps.filterd (m0279871.ppops.net [127.0.0.1])
- by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id
- 54LIZCMW000836;
- Wed, 21 May 2025 22:45:53 GMT
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=
- cc:content-transfer-encoding:content-type:date:from:in-reply-to
- :message-id:mime-version:references:subject:to; s=qcppdkim1; bh=
- jJ/9931jjDg+8neUbH09oigyzQwINmgJKgsYw6rWwPU=; b=gwsO0461NDm4hzMy
- /aP5LNjbfqB08SmlMEzcZ/MRNS7Ffjdvz9gsUyJR4DOilx71C5MvB0ZBvxEJF6pg
- qcU4QPZtOzyixWx+3vL6eh4Sdt/RN5AD/6U6TJEZCPwdJNLMD5uB2OQjP87NG9Wj
- 2aEs+kb//lRXz6Gy5d7CCDW3+1KSDzgIg/cYJecPjWsMKbyCxTeFTIkkdonetQyz
- PSzkIDi3IBnca94koYTQyFTVvpUVHpC3QAq+jM9+xQJOItRbDHZjdPjLG6q1ML4W
- zYHODhd8LupxL323rnWJQxtYu5Ver7g2LgPW3npNz/JEdF2Hq9b8G0w5U8qVJVHr
- 2nNuUA==
-Received: from nalasppmta05.qualcomm.com (Global_NAT1.qualcomm.com
- [129.46.96.20])
- by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwf6vbsd-1
- (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
- Wed, 21 May 2025 22:45:53 +0000 (GMT)
-Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com
- [10.47.209.196])
- by NALASPPMTA05.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id
- 54LMjqLl023280
- (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
- Wed, 21 May 2025 22:45:52 GMT
-Received: from ath12k-linux2.qualcomm.com (10.80.80.8) by
- nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server
- (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
- 15.2.1544.9; Wed, 21 May 2025 15:45:51 -0700
- Pradeep Kumar Chitrapu
- "Jeff
-Subject: [PATCH ath-next V14 1/9] wifi: ath12k: push HE MU-MIMO params to
- hardware
-Date: Wed, 21 May 2025 15:45:31 -0700
-X-Mailer: git-send-email 2.43.0
-Precedence: bulk
-List-Id: <linux-wireless.vger.kernel.org>
-MIME-Version: 1.0
-X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To
- nalasex01a.na.qualcomm.com (10.47.209.196)
-X-QCInternal: smtphost
-X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800
- signatures=585085
-X-Proofpoint-GUID: Zzf2Q5y4JzSN5f1E_vlCnvLRODG4zasa
-X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIxMDIyNiBTYWx0ZWRfXyLZVeJQcQf0U
- B/O6/0+L+1nXg6SAFSC1bdc8B/eF8RxRnvbbX+YkF3RG14/UHGCF654g8ZXTq8oTCDzm3x5wmAk
- i8wAlv0otog8iYaicRd5q/x9Vynwlo0e67/iHhH1K0rxsp5yagZ6L3XLS82iLDPuXzHP7ylgo+I
- D0c1CMcLo4bGNe421uQk2jqRij3j1iAoI0gGSwcQqHRucJQSYetF+SSp/oDox9Dn2TqOagngt4V
- UxzAxO13SoH2X7RyWe5NxhfbEjOUmHjfodyJhBfIYh4s5SCx8IDUn6jSorAnl5mh1ZmAfISyZCC
- UqoQ2LDdmGl1HT3d4xvb7/ah09ru4wukKEcvP+HDrow6Xn/WsfgmRy6xdRv5vdNODiEv64XOGHa
- TxrJA2l36xRwX82xvkyUzyQ1sIeXwbvD0Wn//AQSmFVE0uMJHnCwRE1OYRGf9Dd2p/mfZfFh
-X-Authority-Analysis: v=2.4 cv=fZOty1QF c=1 sm=1 tr=0 ts=682e57a1 cx=c_pps
- a=ouPCqIW2jiPt+lZRy3xVPw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17
- a=GEpy-HfZoHoA:10 a=dt9VzEwgFbYA:10 a=COk6AnOGAAAA:8 a=-_O-Wy8N5QNPZvNXkjkA:9
- a=TjNXssC_j7lpFel5tvFf:22
-X-Proofpoint-ORIG-GUID: Zzf2Q5y4JzSN5f1E_vlCnvLRODG4zasa
-X-Proofpoint-Virus-Version: vendor=baseguard
- engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40
- definitions=2025-05-21_07,2025-05-20_03,2025-03-28_01
-X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0
- clxscore=1015 mlxscore=0 adultscore=0 spamscore=0 bulkscore=0 suspectscore=0
- malwarescore=0 priorityscore=1501 impostorscore=0 mlxlogscore=999
- lowpriorityscore=0 phishscore=0 classifier=spam authscore=0 authtc=n/a
- authcc= route=outbound adjust=0 reason=mlx scancount=1
- engine=8.19.0-2505160000 definitions=main-2505210226
-
-Currently, only the HE IE in management frames is updated with
-respect to MU-MIMO configurations, but this change is not
-reflected in the hardware. Add support to propagate MU-MIMO
-configurations to the hardware as well.
-
-Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
-
----
- drivers/net/wireless/ath/ath12k/mac.c | 228 +++++++++++++++++---------
- drivers/net/wireless/ath/ath12k/mac.h | 15 ++
- drivers/net/wireless/ath/ath12k/wmi.h | 28 +---
- 3 files changed, 169 insertions(+), 102 deletions(-)
-
---- a/drivers/net/wireless/ath/ath12k/mac.c
-+++ b/drivers/net/wireless/ath/ath12k/mac.c
-@@ -3173,6 +3173,125 @@ static u32 ath12k_mac_ieee80211_sta_bw_t
- return bw;
- }
-
-+static int ath12k_mac_set_he_txbf_conf(struct ath12k_link_vif *arvif)
-+{
-+ struct ath12k_vif *ahvif = arvif->ahvif;
-+ struct ath12k *ar = arvif->ar;
-+ u32 param = WMI_VDEV_PARAM_SET_HEMU_MODE;
-+ u32 value = 0;
-+ int ret;
-+ struct ieee80211_bss_conf *link_conf;
-+
-+ link_conf = ath12k_mac_get_link_bss_conf(arvif);
-+ if (!link_conf) {
-+ ath12k_warn(ar->ab, "unable to access bss link conf in txbf conf\n");
-+ return -EINVAL;
-+ }
-+
-+ if (!link_conf->he_support)
-+ return 0;
-+
-+ if (link_conf->he_su_beamformer) {
-+ value |= u32_encode_bits(HE_SU_BFER_ENABLE, HE_MODE_SU_TX_BFER);
-+ if (link_conf->he_mu_beamformer &&
-+ ahvif->vdev_type == WMI_VDEV_TYPE_AP)
-+ value |= u32_encode_bits(HE_MU_BFER_ENABLE, HE_MODE_MU_TX_BFER);
-+ }
-+
-+ if (ahvif->vif->type != NL80211_IFTYPE_MESH_POINT) {
-+ value |= u32_encode_bits(HE_DL_MUOFDMA_ENABLE, HE_MODE_DL_OFDMA) |
-+ u32_encode_bits(HE_UL_MUOFDMA_ENABLE, HE_MODE_UL_OFDMA);
-+
-+ if (link_conf->he_full_ul_mumimo)
-+ value |= u32_encode_bits(HE_UL_MUMIMO_ENABLE, HE_MODE_UL_MUMIMO);
-+
-+ if (link_conf->he_su_beamformee)
-+ value |= u32_encode_bits(HE_SU_BFEE_ENABLE, HE_MODE_SU_TX_BFEE);
-+ }
-+
-+ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param, value);
-+ if (ret) {
-+ ath12k_warn(ar->ab, "failed to set vdev %d HE MU mode: %d\n",
-+ arvif->vdev_id, ret);
-+ return ret;
-+ }
-+
-+ param = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE;
-+ value = u32_encode_bits(HE_VHT_SOUNDING_MODE_ENABLE, HE_VHT_SOUNDING_MODE) |
-+ u32_encode_bits(HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE,
-+ HE_TRIG_NONTRIG_SOUNDING_MODE);
-+ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
-+ param, value);
-+ if (ret) {
-+ ath12k_warn(ar->ab, "failed to set vdev %d sounding mode: %d\n",
-+ arvif->vdev_id, ret);
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
-+static int ath12k_mac_vif_recalc_sta_he_txbf(struct ath12k *ar,
-+ struct ath12k_link_vif *arvif,
-+ struct ieee80211_sta_he_cap *he_cap,
-+ int *hemode)
-+{
-+ struct ieee80211_vif *vif = arvif->ahvif->vif;
-+ struct ieee80211_he_cap_elem he_cap_elem = {};
-+ struct ieee80211_sta_he_cap *cap_band;
-+ struct cfg80211_chan_def def;
-+ u8 link_id = arvif->link_id;
-+ struct ieee80211_bss_conf *link_conf;
-+
-+ link_conf = ath12k_mac_get_link_bss_conf(arvif);
-+ if (!link_conf) {
-+ ath12k_warn(ar->ab, "unable to access bss link conf in recalc txbf conf\n");
-+ return -EINVAL;
-+ }
-+
-+ if (!link_conf->he_support)
-+ return 0;
-+
-+ if (vif->type != NL80211_IFTYPE_STATION)
-+ return -EINVAL;
-+
-+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, link_id, &def)))
-+ return -EINVAL;
-+
-+ if (def.chan->band == NL80211_BAND_2GHZ)
-+ cap_band = &ar->mac.iftype[NL80211_BAND_2GHZ][vif->type].he_cap;
-+ else
-+ cap_band = &ar->mac.iftype[NL80211_BAND_5GHZ][vif->type].he_cap;
-+
-+ memcpy(&he_cap_elem, &cap_band->he_cap_elem, sizeof(he_cap_elem));
-+
-+ *hemode = 0;
-+ if (HECAP_PHY_SUBFME_GET(he_cap_elem.phy_cap_info)) {
-+ if (HECAP_PHY_SUBFMR_GET(he_cap->he_cap_elem.phy_cap_info))
-+ *hemode |= u32_encode_bits(HE_SU_BFEE_ENABLE, HE_MODE_SU_TX_BFEE);
-+ if (HECAP_PHY_MUBFMR_GET(he_cap->he_cap_elem.phy_cap_info))
-+ *hemode |= u32_encode_bits(HE_MU_BFEE_ENABLE, HE_MODE_MU_TX_BFEE);
-+ }
-+
-+ if (vif->type != NL80211_IFTYPE_MESH_POINT) {
-+ *hemode |= u32_encode_bits(HE_DL_MUOFDMA_ENABLE, HE_MODE_DL_OFDMA) |
-+ u32_encode_bits(HE_UL_MUOFDMA_ENABLE, HE_MODE_UL_OFDMA);
-+
-+ if (HECAP_PHY_ULMUMIMO_GET(he_cap_elem.phy_cap_info))
-+ if (HECAP_PHY_ULMUMIMO_GET(he_cap->he_cap_elem.phy_cap_info))
-+ *hemode |= u32_encode_bits(HE_UL_MUMIMO_ENABLE,
-+ HE_MODE_UL_MUMIMO);
-+
-+ if (u32_get_bits(*hemode, HE_MODE_MU_TX_BFEE))
-+ *hemode |= u32_encode_bits(HE_SU_BFEE_ENABLE, HE_MODE_SU_TX_BFEE);
-+
-+ if (u32_get_bits(*hemode, HE_MODE_MU_TX_BFER))
-+ *hemode |= u32_encode_bits(HE_SU_BFER_ENABLE, HE_MODE_SU_TX_BFER);
-+ }
-+
-+ return 0;
-+}
-+
- static void ath12k_bss_assoc(struct ath12k *ar,
- struct ath12k_link_vif *arvif,
- struct ieee80211_bss_conf *bss_conf)
-@@ -3187,6 +3306,7 @@ static void ath12k_bss_assoc(struct ath1
- struct ath12k_sta *ahsta;
- struct ath12k_peer *peer;
- bool is_auth = false;
-+ u32 hemode = 0;
- int ret;
-
- lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
-@@ -3230,8 +3350,26 @@ static void ath12k_bss_assoc(struct ath1
-
- ath12k_peer_assoc_prepare(ar, arvif, arsta, peer_arg, false);
-
-+ /* link_sta->he_cap must be protected by rcu_read_lock */
-+ ret = ath12k_mac_vif_recalc_sta_he_txbf(ar, arvif, &link_sta->he_cap, &hemode);
-+ if (ret) {
-+ ath12k_warn(ar->ab, "failed to recalc he txbf for vdev %i on bss %pM: %d\n",
-+ arvif->vdev_id, bss_conf->bssid, ret);
-+ rcu_read_unlock();
-+ return;
-+ }
-+
- rcu_read_unlock();
-
-+ /* keep this before ath12k_wmi_send_peer_assoc_cmd() */
-+ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
-+ WMI_VDEV_PARAM_SET_HEMU_MODE, hemode);
-+ if (ret) {
-+ ath12k_warn(ar->ab, "failed to submit vdev param txbf 0x%x: %d\n",
-+ hemode, ret);
-+ return;
-+ }
-+
- ret = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg);
- if (ret) {
- ath12k_warn(ar->ab, "failed to run peer assoc for %pM vdev %i: %d\n",
-@@ -3850,6 +3988,13 @@ static void ath12k_mac_bss_info_changed(
- ether_addr_copy(arvif->bssid, info->bssid);
-
- if (changed & BSS_CHANGED_BEACON_ENABLED) {
-+ if (info->enable_beacon) {
-+ ret = ath12k_mac_set_he_txbf_conf(arvif);
-+ if (ret)
-+ ath12k_warn(ar->ab,
-+ "failed to set HE TXBF config for vdev: %d\n",
-+ arvif->vdev_id);
-+ }
- ath12k_control_beaconing(arvif, info);
-
- if (arvif->is_up && info->he_support &&
-@@ -7151,11 +7296,14 @@ static void ath12k_mac_copy_he_cap(struc
-
- he_cap_elem->mac_cap_info[1] &=
- IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;
--
-+ he_cap_elem->phy_cap_info[0] &=
-+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
-+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
-+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
-+ he_cap_elem->phy_cap_info[0] &=
-+ ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G;
- he_cap_elem->phy_cap_info[5] &=
- ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
-- he_cap_elem->phy_cap_info[5] &=
-- ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;
- he_cap_elem->phy_cap_info[5] |= num_tx_chains - 1;
-
- switch (iftype) {
-@@ -8454,72 +8602,6 @@ static int ath12k_mac_setup_vdev_create_
- return 0;
- }
-
--static u32
--ath12k_mac_prepare_he_mode(struct ath12k_pdev *pdev, u32 viftype)
--{
-- struct ath12k_pdev_cap *pdev_cap = &pdev->cap;
-- struct ath12k_band_cap *cap_band = NULL;
-- u32 *hecap_phy_ptr = NULL;
-- u32 hemode;
--
-- if (pdev->cap.supported_bands & WMI_HOST_WLAN_2GHZ_CAP)
-- cap_band = &pdev_cap->band[NL80211_BAND_2GHZ];
-- else
-- cap_band = &pdev_cap->band[NL80211_BAND_5GHZ];
--
-- hecap_phy_ptr = &cap_band->he_cap_phy_info[0];
--
-- hemode = u32_encode_bits(HE_SU_BFEE_ENABLE, HE_MODE_SU_TX_BFEE) |
-- u32_encode_bits(HECAP_PHY_SUBFMR_GET(hecap_phy_ptr),
-- HE_MODE_SU_TX_BFER) |
-- u32_encode_bits(HECAP_PHY_ULMUMIMO_GET(hecap_phy_ptr),
-- HE_MODE_UL_MUMIMO);
--
-- /* TODO: WDS and other modes */
-- if (viftype == NL80211_IFTYPE_AP) {
-- hemode |= u32_encode_bits(HECAP_PHY_MUBFMR_GET(hecap_phy_ptr),
-- HE_MODE_MU_TX_BFER) |
-- u32_encode_bits(HE_DL_MUOFDMA_ENABLE, HE_MODE_DL_OFDMA) |
-- u32_encode_bits(HE_UL_MUOFDMA_ENABLE, HE_MODE_UL_OFDMA);
-- } else {
-- hemode |= u32_encode_bits(HE_MU_BFEE_ENABLE, HE_MODE_MU_TX_BFEE);
-- }
--
-- return hemode;
--}
--
--static int ath12k_set_he_mu_sounding_mode(struct ath12k *ar,
-- struct ath12k_link_vif *arvif)
--{
-- u32 param_id, param_value;
-- struct ath12k_base *ab = ar->ab;
-- struct ath12k_vif *ahvif = arvif->ahvif;
-- int ret;
--
-- param_id = WMI_VDEV_PARAM_SET_HEMU_MODE;
-- param_value = ath12k_mac_prepare_he_mode(ar->pdev, ahvif->vif->type);
-- ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
-- param_id, param_value);
-- if (ret) {
-- ath12k_warn(ab, "failed to set vdev %d HE MU mode: %d param_value %x\n",
-- arvif->vdev_id, ret, param_value);
-- return ret;
-- }
-- param_id = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE;
-- param_value =
-- u32_encode_bits(HE_VHT_SOUNDING_MODE_ENABLE, HE_VHT_SOUNDING_MODE) |
-- u32_encode_bits(HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE,
-- HE_TRIG_NONTRIG_SOUNDING_MODE);
-- ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
-- param_id, param_value);
-- if (ret) {
-- ath12k_warn(ab, "failed to set vdev %d HE MU mode: %d\n",
-- arvif->vdev_id, ret);
-- return ret;
-- }
-- return ret;
--}
--
- static void ath12k_mac_update_vif_offload(struct ath12k_link_vif *arvif)
- {
- struct ath12k_vif *ahvif = arvif->ahvif;
-@@ -9706,14 +9788,6 @@ ath12k_mac_vdev_start_restart(struct ath
- spin_unlock_bh(&ab->base_lock);
-
- /* TODO: Notify if secondary 80Mhz also needs radar detection */
-- if (link_conf->he_support) {
-- ret = ath12k_set_he_mu_sounding_mode(ar, arvif);
-- if (ret) {
-- ath12k_warn(ar->ab, "failed to set he mode vdev %i\n",
-- arg.vdev_id);
-- return ret;
-- }
-- }
- }
-
- arg.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
---- a/drivers/net/wireless/ath/ath12k/mac.h
-+++ b/drivers/net/wireless/ath/ath12k/mac.h
-@@ -56,6 +56,21 @@ struct ath12k_generic_iter {
-
- #define ATH12K_NUM_MAX_ACTIVE_LINKS_PER_DEVICE 2
-
-+#define HECAP_PHY_SUBFMR_GET(hecap_phy) \
-+ u8_get_bits(hecap_phy[3], IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER)
-+
-+#define HECAP_PHY_SUBFME_GET(hecap_phy) \
-+ u8_get_bits(hecap_phy[4], IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE)
-+
-+#define HECAP_PHY_MUBFMR_GET(hecap_phy) \
-+ u8_get_bits(hecap_phy[4], IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER)
-+
-+#define HECAP_PHY_ULMUMIMO_GET(hecap_phy) \
-+ u8_get_bits(hecap_phy[2], IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO)
-+
-+#define HECAP_PHY_ULOFDMA_GET(hecap_phy) \
-+ u8_get_bits(hecap_phy[2], IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO)
-+
- enum ath12k_supported_bw {
- ATH12K_BW_20 = 0,
- ATH12K_BW_40 = 1,
---- a/drivers/net/wireless/ath/ath12k/wmi.h
-+++ b/drivers/net/wireless/ath/ath12k/wmi.h
-@@ -3131,31 +3131,6 @@ struct ath12k_wmi_rx_reorder_queue_remov
- #define WMI_VDEV_PARAM_TXBF_SU_TX_BFER BIT(2)
- #define WMI_VDEV_PARAM_TXBF_MU_TX_BFER BIT(3)
-
--#define HECAP_PHYDWORD_0 0
--#define HECAP_PHYDWORD_1 1
--#define HECAP_PHYDWORD_2 2
--
--#define HECAP_PHY_SU_BFER BIT(31)
--#define HECAP_PHY_SU_BFEE BIT(0)
--#define HECAP_PHY_MU_BFER BIT(1)
--#define HECAP_PHY_UL_MUMIMO BIT(22)
--#define HECAP_PHY_UL_MUOFDMA BIT(23)
--
--#define HECAP_PHY_SUBFMR_GET(hecap_phy) \
-- u32_get_bits(hecap_phy[HECAP_PHYDWORD_0], HECAP_PHY_SU_BFER)
--
--#define HECAP_PHY_SUBFME_GET(hecap_phy) \
-- u32_get_bits(hecap_phy[HECAP_PHYDWORD_1], HECAP_PHY_SU_BFEE)
--
--#define HECAP_PHY_MUBFMR_GET(hecap_phy) \
-- u32_get_bits(hecap_phy[HECAP_PHYDWORD_1], HECAP_PHY_MU_BFER)
--
--#define HECAP_PHY_ULMUMIMO_GET(hecap_phy) \
-- u32_get_bits(hecap_phy[HECAP_PHYDWORD_0], HECAP_PHY_UL_MUMIMO)
--
--#define HECAP_PHY_ULOFDMA_GET(hecap_phy) \
-- u32_get_bits(hecap_phy[HECAP_PHYDWORD_0], HECAP_PHY_UL_MUOFDMA)
--
- #define HE_MODE_SU_TX_BFEE BIT(0)
- #define HE_MODE_SU_TX_BFER BIT(1)
- #define HE_MODE_MU_TX_BFEE BIT(2)
-@@ -3167,8 +3142,11 @@ struct ath12k_wmi_rx_reorder_queue_remov
- #define HE_DL_MUOFDMA_ENABLE 1
- #define HE_UL_MUOFDMA_ENABLE 1
- #define HE_DL_MUMIMO_ENABLE 1
-+#define HE_UL_MUMIMO_ENABLE 1
- #define HE_MU_BFEE_ENABLE 1
- #define HE_SU_BFEE_ENABLE 1
-+#define HE_MU_BFER_ENABLE 1
-+#define HE_SU_BFER_ENABLE 1
-
- #define HE_VHT_SOUNDING_MODE_ENABLE 1
- #define HE_SU_MU_SOUNDING_MODE_ENABLE 1
+++ /dev/null
-From patchwork Wed May 21 22:45:32 2025
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Id: 14096119
-Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com
- [205.220.180.131])
- (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
- (No client certificate requested)
- by smtp.subspace.kernel.org (Postfix) with ESMTPS id 697B71A23AA
-Authentication-Results: smtp.subspace.kernel.org;
- arc=none smtp.client-ip=205.220.180.131
-ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
- t=1747867560; cv=none;
- b=XceXZ7CY2+FEzM9RuC10/cGW+vmyB2cX8QWJ3ckav7jiY5NYBQe1XW2asWcHaAEmOwdUh2iRT6imeiQLYue78g4UAcBErvihTGqlYL0m+10CQMNHmQZurUQkLPeFS0WAwlA+HBgcdp+Z71PhXs/ttQD6dF/8mlPaeGqxlTUoEcM=
-ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
- s=arc-20240116; t=1747867560; c=relaxed/simple;
- bh=mXjCwVOeMuqCjiNDATjkwHPrwNjm6Uv3d5yO5+bqbfk=;
- h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:
- MIME-Version:Content-Type;
- b=SeDDAI+0lqXCMqhleIhxgpdPq9QuWaPI9jj0JOqYiwOIVtAsNqQv7KQ+AMvXDQTsIe0LfA2l23stlXB7sLNpKHTM9JhPsLkafU7mvBaiwTxaJR5tEi4zGQZhsrKSn/awYszamnM81hQS3r9bBgS4oe8AeFV2/lDXYPXNHCGv0+w=
-ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
- dmarc=pass (p=none dis=none) header.from=quicinc.com;
- spf=pass smtp.mailfrom=quicinc.com;
- header.b=DwzHO5rL; arc=none smtp.client-ip=205.220.180.131
-Authentication-Results: smtp.subspace.kernel.org;
- dmarc=pass (p=none dis=none) header.from=quicinc.com
-Authentication-Results: smtp.subspace.kernel.org;
- spf=pass smtp.mailfrom=quicinc.com
-Authentication-Results: smtp.subspace.kernel.org;
- header.b="DwzHO5rL"
-Received: from pps.filterd (m0279869.ppops.net [127.0.0.1])
- by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id
- 54LJflLg012749;
- Wed, 21 May 2025 22:45:53 GMT
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=
- cc:content-transfer-encoding:content-type:date:from:in-reply-to
- :message-id:mime-version:references:subject:to; s=qcppdkim1; bh=
- tiHJ0bp145D1K0TKBussv+a5p9S+5sP37NuNrmk03fg=; b=DwzHO5rLl1Vp87qm
- lpxifM2nR9pLT0mgMqz/HRb/yTHCnS9oGDXzc24mnve2I/O9X/YT8q8qN+wjBlLB
- 4W7snIItVpffzrSmAJupTNtzj8qbmIYeti1zUlDdVoesUaICbdiDvSeCWPUtfeaz
- tNKDOmBUTvCb+1qxxciQZhuRobmmkuRgcg8VkgCFP+OyG5o1OrUESYu3QeZ62Hle
- ODt78jw+qe8cE9e2TxGEZhy++loik0tbF8D9P3cX5L+CdB+i4TyWnFxwvNgJciIx
- RptE1lyB75UdrnAqETq0km4svwyidUuum/x0hqd6TvlDod3b7FD4tjbE7EP5iQ5V
- Dw2tXA==
-Received: from nalasppmta01.qualcomm.com (Global_NAT1.qualcomm.com
- [129.46.96.20])
- by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwf9carr-1
- (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
- Wed, 21 May 2025 22:45:53 +0000 (GMT)
-Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com
- [10.47.209.196])
- by NALASPPMTA01.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id
- 54LMjqtS008810
- (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
- Wed, 21 May 2025 22:45:52 GMT
-Received: from ath12k-linux2.qualcomm.com (10.80.80.8) by
- nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server
- (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
- 15.2.1544.9; Wed, 21 May 2025 15:45:52 -0700
- Pradeep Kumar Chitrapu
- "Jeff
-Subject: [PATCH ath-next V14 2/9] wifi: ath12k: push EHT MU-MIMO params to
- hardware
-Date: Wed, 21 May 2025 15:45:32 -0700
-X-Mailer: git-send-email 2.43.0
-Precedence: bulk
-List-Id: <linux-wireless.vger.kernel.org>
-MIME-Version: 1.0
-X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To
- nalasex01a.na.qualcomm.com (10.47.209.196)
-X-QCInternal: smtphost
-X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800
- signatures=585085
-X-Proofpoint-ORIG-GUID: _eaDrXLa14UhDtRJT-hk8Y6z1fwFI6QB
-X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIxMDIyNSBTYWx0ZWRfX7QgTyyXEHZM8
- OnUvphQD/4J77Z8iHm4hJQIe6duMI5HbpiWELH5aRxqU7pFuvCjmltcmWPjwls9DzTkJnDGHMjo
- FuBarQpMaZO8eQsx97aM8WpE0dpJHROE1ZRZ3SV8VEoTHHG712fvPw+oUWaZo6WccaEbxH9x9+W
- n76tkFOOopbjRgOBmCokHCrfZmCMKcT4FLUFoiIDn0Fv8b/WKaut3Z+1hrEwcOuXCJv4X1QIOcx
- 6NCnxNr8y1O1cwqXg3pBhHB+BpcLiEat6TlD9bH/5oUZHFce4W1jkZYs2J5VJnzLDeQxq8xBhP0
- Qal3bpuUPyWAMKZKH/uAEXwEZ5ZMghUioGuc78EBMJhSXa2VsT3lhmJtc/CaHDqNKFrp01I/KAh
- 7UcIN/PKb8qOKrHE8/8cpuHgoBgB24X84Qo5rORKfnW4s7FbS0xkcs2ZV2TI0AIGz4eEZAOY
-X-Authority-Analysis: v=2.4 cv=GawXnRXL c=1 sm=1 tr=0 ts=682e57a1 cx=c_pps
- a=ouPCqIW2jiPt+lZRy3xVPw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17
- a=GEpy-HfZoHoA:10 a=dt9VzEwgFbYA:10 a=COk6AnOGAAAA:8 a=uoU_VXRAPQDrZd00miQA:9
- a=TjNXssC_j7lpFel5tvFf:22
-X-Proofpoint-GUID: _eaDrXLa14UhDtRJT-hk8Y6z1fwFI6QB
-X-Proofpoint-Virus-Version: vendor=baseguard
- engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40
- definitions=2025-05-21_07,2025-05-20_03,2025-03-28_01
-X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0
- mlxscore=0 mlxlogscore=999 lowpriorityscore=0 impostorscore=0
- priorityscore=1501 clxscore=1015 malwarescore=0 phishscore=0 bulkscore=0
- spamscore=0 suspectscore=0 adultscore=0 classifier=spam authscore=0
- authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1
- engine=8.19.0-2505160000 definitions=main-2505210225
-
-Currently, only the EHT IE in management frames is updated with
-respect to MU-MIMO configurations, but this change is not
-reflected in the hardware. Add support to propagate MU-MIMO
-configurations to the hardware as well for AP mode. Similar
-support for STA mode will be added in future.
-
-Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
-
----
- drivers/net/wireless/ath/ath12k/mac.c | 58 +++++++++++++++++++++++++++
- drivers/net/wireless/ath/ath12k/wmi.h | 21 ++++++++++
- 2 files changed, 79 insertions(+)
-
---- a/drivers/net/wireless/ath/ath12k/mac.c
-+++ b/drivers/net/wireless/ath/ath12k/mac.c
-@@ -3292,6 +3292,58 @@ static int ath12k_mac_vif_recalc_sta_he_
- return 0;
- }
-
-+static int ath12k_mac_set_eht_txbf_conf(struct ath12k_link_vif *arvif)
-+{
-+ struct ath12k_vif *ahvif = arvif->ahvif;
-+ struct ath12k *ar = arvif->ar;
-+ u32 param = WMI_VDEV_PARAM_SET_EHT_MU_MODE;
-+ u32 value = 0;
-+ int ret;
-+ struct ieee80211_bss_conf *link_conf;
-+
-+ link_conf = ath12k_mac_get_link_bss_conf(arvif);
-+ if (!link_conf) {
-+ ath12k_warn(ar->ab, "unable to access bss link conf in eht txbf conf\n");
-+ return -ENOENT;
-+ }
-+
-+ if (!link_conf->eht_support)
-+ return 0;
-+
-+ if (link_conf->eht_su_beamformer) {
-+ value |= u32_encode_bits(EHT_SU_BFER_ENABLE, EHT_MODE_SU_TX_BFER);
-+ if (link_conf->eht_mu_beamformer &&
-+ ahvif->vdev_type == WMI_VDEV_TYPE_AP)
-+ value |= u32_encode_bits(EHT_MU_BFER_ENABLE,
-+ EHT_MODE_MU_TX_BFER) |
-+ u32_encode_bits(EHT_DL_MUOFDMA_ENABLE,
-+ EHT_MODE_DL_OFDMA_MUMIMO) |
-+ u32_encode_bits(EHT_UL_MUOFDMA_ENABLE,
-+ EHT_MODE_UL_OFDMA_MUMIMO);
-+ }
-+
-+ if (ahvif->vif->type != NL80211_IFTYPE_MESH_POINT) {
-+ value |= u32_encode_bits(EHT_DL_MUOFDMA_ENABLE, EHT_MODE_DL_OFDMA) |
-+ u32_encode_bits(EHT_UL_MUOFDMA_ENABLE, EHT_MODE_UL_OFDMA);
-+
-+ if (link_conf->eht_80mhz_full_bw_ul_mumimo)
-+ value |= u32_encode_bits(EHT_UL_MUMIMO_ENABLE, EHT_MODE_MUMIMO);
-+
-+ if (link_conf->eht_su_beamformee)
-+ value |= u32_encode_bits(EHT_SU_BFEE_ENABLE,
-+ EHT_MODE_SU_TX_BFEE);
-+ }
-+
-+ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param, value);
-+ if (ret) {
-+ ath12k_warn(ar->ab, "failed to set vdev %d EHT MU mode: %d\n",
-+ arvif->vdev_id, ret);
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
- static void ath12k_bss_assoc(struct ath12k *ar,
- struct ath12k_link_vif *arvif,
- struct ieee80211_bss_conf *bss_conf)
-@@ -3994,6 +4046,12 @@ static void ath12k_mac_bss_info_changed(
- ath12k_warn(ar->ab,
- "failed to set HE TXBF config for vdev: %d\n",
- arvif->vdev_id);
-+
-+ ret = ath12k_mac_set_eht_txbf_conf(arvif);
-+ if (ret)
-+ ath12k_warn(ar->ab,
-+ "failed to set EHT TXBF config for vdev: %d\n",
-+ arvif->vdev_id);
- }
- ath12k_control_beaconing(arvif, info);
-
---- a/drivers/net/wireless/ath/ath12k/wmi.h
-+++ b/drivers/net/wireless/ath/ath12k/wmi.h
-@@ -1176,6 +1176,7 @@ enum wmi_tlv_vdev_param {
- WMI_VDEV_PARAM_BSS_COLOR,
- WMI_VDEV_PARAM_SET_HEMU_MODE,
- WMI_VDEV_PARAM_HEOPS_0_31 = 0x8003,
-+ WMI_VDEV_PARAM_SET_EHT_MU_MODE = 0x8005,
- };
-
- enum wmi_tlv_peer_flags {
-@@ -3148,6 +3149,26 @@ struct ath12k_wmi_rx_reorder_queue_remov
- #define HE_MU_BFER_ENABLE 1
- #define HE_SU_BFER_ENABLE 1
-
-+#define EHT_MODE_SU_TX_BFEE BIT(0)
-+#define EHT_MODE_SU_TX_BFER BIT(1)
-+#define EHT_MODE_MU_TX_BFEE BIT(2)
-+#define EHT_MODE_MU_TX_BFER BIT(3)
-+#define EHT_MODE_DL_OFDMA BIT(4)
-+#define EHT_MODE_UL_OFDMA BIT(5)
-+#define EHT_MODE_MUMIMO BIT(6)
-+#define EHT_MODE_DL_OFDMA_TXBF BIT(7)
-+#define EHT_MODE_DL_OFDMA_MUMIMO BIT(8)
-+#define EHT_MODE_UL_OFDMA_MUMIMO BIT(9)
-+
-+#define EHT_DL_MUOFDMA_ENABLE 1
-+#define EHT_UL_MUOFDMA_ENABLE 1
-+#define EHT_DL_MUMIMO_ENABLE 1
-+#define EHT_UL_MUMIMO_ENABLE 1
-+#define EHT_MU_BFEE_ENABLE 1
-+#define EHT_SU_BFEE_ENABLE 1
-+#define EHT_MU_BFER_ENABLE 1
-+#define EHT_SU_BFER_ENABLE 1
-+
- #define HE_VHT_SOUNDING_MODE_ENABLE 1
- #define HE_SU_MU_SOUNDING_MODE_ENABLE 1
- #define HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE 1
+++ /dev/null
-From patchwork Wed May 21 22:45:33 2025
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Id: 14096126
-Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com
- [205.220.168.131])
- (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
- (No client certificate requested)
- by smtp.subspace.kernel.org (Postfix) with ESMTPS id A4E00239570
-Authentication-Results: smtp.subspace.kernel.org;
- arc=none smtp.client-ip=205.220.168.131
-ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
- t=1747867563; cv=none;
- b=m0NU8tyG2d1pHiYNjTYhCTeGXC0pFtHNZTKxb+dc5AEzzUCa75lxPxtYFZApv1QHaLqo3lGkZ+ADhqhj/V82GA+bUeetm3hSsnyGgjbayU3IzqeO09+VPkt9sx9hdrTMlVGEI4c5881Zho41rlVW65O/SlmqRi4J/ajQzA4tiGQ=
-ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
- s=arc-20240116; t=1747867563; c=relaxed/simple;
- bh=0bTV82dMwisd7nmbtolnSKswG/aTjqN0YxpAx66Oqv8=;
- h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:
- MIME-Version:Content-Type;
- b=jOkezej/N9fmvOtPNCGPpnPNtoQ+pAG4k1zAiw3xnL1iikk7VcJlbXDCrGUithxMZE2513zz/fsfDjXx0AMi4YT1ISljvGCw9B0dGQ5ECiFfoGLc+12nnsvqjiXI5zla6C1iX7bgtJjv/OYWzoY0TR5jI28CZWC/Pa9fT/X0duw=
-ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
- dmarc=pass (p=none dis=none) header.from=quicinc.com;
- spf=pass smtp.mailfrom=quicinc.com;
- header.b=UqUMYAcW; arc=none smtp.client-ip=205.220.168.131
-Authentication-Results: smtp.subspace.kernel.org;
- dmarc=pass (p=none dis=none) header.from=quicinc.com
-Authentication-Results: smtp.subspace.kernel.org;
- spf=pass smtp.mailfrom=quicinc.com
-Authentication-Results: smtp.subspace.kernel.org;
- header.b="UqUMYAcW"
-Received: from pps.filterd (m0279866.ppops.net [127.0.0.1])
- by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id
- 54LIDlKw013406;
- Wed, 21 May 2025 22:45:53 GMT
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=
- cc:content-transfer-encoding:content-type:date:from:in-reply-to
- :message-id:mime-version:references:subject:to; s=qcppdkim1; bh=
- tYXOeicncMlFjsw5kmnB5kxC/Nrj/HibF1jgO4m8lhM=; b=UqUMYAcWWQ07Z79h
- GESSroshxr6zIUBw3jr/ESGDCO554RYWZZh9PXJxjTRM3ceCrNHNpCAT+mqXXiWy
- eb+l7G0W+s1l/MStBq7B43CSdKxljZtlkC/JsHk6DQjBacQzVB8qAiq3ShbR/vn7
- ud3kzjHtYsfLvIpi+8wLTkE1in8E/CUFZ4bea866xldnrcOVEa7EuxKwKXj3sLhE
- 8n3IsPUIYGLKnEFkmWFZTXTqlEOV9lVYdTxeDAUBxII8PQIKu+dlB/UWffTFTSOd
- aQDPK5N6y8x29E2fugyy2XBSEFskz50Jb60+kJhHFGTgl5cQw+NfymuC9SQJBWaE
- HFZu+w==
-Received: from nalasppmta02.qualcomm.com (Global_NAT1.qualcomm.com
- [129.46.96.20])
- by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwh5cfg1-1
- (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
- Wed, 21 May 2025 22:45:53 +0000 (GMT)
-Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com
- [10.47.209.196])
- by NALASPPMTA02.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id
- 54LMjqn9020293
- (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
- Wed, 21 May 2025 22:45:52 GMT
-Received: from ath12k-linux2.qualcomm.com (10.80.80.8) by
- nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server
- (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
- 15.2.1544.9; Wed, 21 May 2025 15:45:52 -0700
- Pradeep Kumar Chitrapu
- "Jeff
-Subject: [PATCH ath-next V14 3/9] wifi: ath12k: move HE MCS mapper to a
- separate function
-Date: Wed, 21 May 2025 15:45:33 -0700
-X-Mailer: git-send-email 2.43.0
-Precedence: bulk
-List-Id: <linux-wireless.vger.kernel.org>
-MIME-Version: 1.0
-X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To
- nalasex01a.na.qualcomm.com (10.47.209.196)
-X-QCInternal: smtphost
-X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800
- signatures=585085
-X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIxMDIyNiBTYWx0ZWRfX0c42ymLt+PTP
- 1OuRw1LMafhFmBy7Y+zhs50WttVxoryUfqamicOcfcFB1N0ReYFgzeQ7geC/w54E8E6mzQDYeie
- WWkPGvuIyvtCjzhBcBwz1A7W/LdsI7Od6+VlXyCuAp4pbCASB7kqVnI7Neak6mvdIQIW5khVLX7
- r/364Kop8/BPQzOVUZf5snfx4TBCgWauiHZQBTJupIn1Tf8+NctUXB8H3QNfu8zJTLVrBA3rtt1
- +yjeNOHom4U/t0u5Vzxu+8XctXsWHoYytfluXbsRo7WNut0MwPSY8GCm7RQ2wDQp0CzdactGb6t
- KCMvNcpkDRjEtOdkNtf2BeVHF1yJKxuibe6qssobLjTadJRkC33xnz5E+hzF6sEZlg7JWok01h4
- OxWFUldQYnF/eQjZYTQcgLyH91h9gWkvz0YJWKGCrg0PlxqeIFS/SQvVNs7qMnsX0qrXb7NV
-X-Authority-Analysis: v=2.4 cv=XeWJzJ55 c=1 sm=1 tr=0 ts=682e57a1 cx=c_pps
- a=ouPCqIW2jiPt+lZRy3xVPw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17
- a=GEpy-HfZoHoA:10 a=dt9VzEwgFbYA:10 a=COk6AnOGAAAA:8 a=4Pgy4kl5F6fn7-PMLAkA:9
- a=TjNXssC_j7lpFel5tvFf:22
-X-Proofpoint-GUID: CVZHk1FyIP3eCYHbVaXVp1fjSAGIjnVJ
-X-Proofpoint-ORIG-GUID: CVZHk1FyIP3eCYHbVaXVp1fjSAGIjnVJ
-X-Proofpoint-Virus-Version: vendor=baseguard
- engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40
- definitions=2025-05-21_07,2025-05-20_03,2025-03-28_01
-X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0
- phishscore=0 clxscore=1015 mlxlogscore=999 mlxscore=0 bulkscore=0 spamscore=0
- suspectscore=0 impostorscore=0 adultscore=0 malwarescore=0 lowpriorityscore=0
- priorityscore=1501 classifier=spam authscore=0 authtc=n/a authcc=
- route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2505160000
- definitions=main-2505210226
-
-Refactor the HE MCS mapper functionality in
-ath12k_mac_copy_he_cap() into a new function.
-
-This helps improve readability, extensibility and will be used
-when adding support for 160 MHz bandwidth in subsequent patches.
-
-Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
-
----
- drivers/net/wireless/ath/ath12k/mac.c | 22 ++++++++++++++--------
- 1 file changed, 14 insertions(+), 8 deletions(-)
-
---- a/drivers/net/wireless/ath/ath12k/mac.c
-+++ b/drivers/net/wireless/ath/ath12k/mac.c
-@@ -7339,12 +7339,24 @@ static __le16 ath12k_mac_setup_he_6ghz_c
- return cpu_to_le16(bcap->he_6ghz_capa);
- }
-
-+static void ath12k_mac_set_hemcsmap(struct ath12k_band_cap *band_cap,
-+ struct ieee80211_sta_he_cap *he_cap)
-+{
-+ struct ieee80211_he_mcs_nss_supp *mcs_nss = &he_cap->he_mcs_nss_supp;
-+
-+ mcs_nss->rx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
-+ mcs_nss->tx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
-+ mcs_nss->rx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
-+ mcs_nss->tx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
-+ mcs_nss->rx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
-+ mcs_nss->tx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
-+}
-+
- static void ath12k_mac_copy_he_cap(struct ath12k_band_cap *band_cap,
- int iftype, u8 num_tx_chains,
- struct ieee80211_sta_he_cap *he_cap)
- {
- struct ieee80211_he_cap_elem *he_cap_elem = &he_cap->he_cap_elem;
-- struct ieee80211_he_mcs_nss_supp *mcs_nss = &he_cap->he_mcs_nss_supp;
-
- he_cap->has_he = true;
- memcpy(he_cap_elem->mac_cap_info, band_cap->he_cap_info,
-@@ -7384,13 +7396,7 @@ static void ath12k_mac_copy_he_cap(struc
- break;
- }
-
-- mcs_nss->rx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
-- mcs_nss->tx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
-- mcs_nss->rx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
-- mcs_nss->tx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
-- mcs_nss->rx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
-- mcs_nss->tx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
--
-+ ath12k_mac_set_hemcsmap(band_cap, he_cap);
- memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
- if (he_cap_elem->phy_cap_info[6] &
- IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)
+++ /dev/null
-From patchwork Wed May 21 22:45:34 2025
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Id: 14096123
-Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com
- [205.220.180.131])
- (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
- (No client certificate requested)
- by smtp.subspace.kernel.org (Postfix) with ESMTPS id A3C04239581
-Authentication-Results: smtp.subspace.kernel.org;
- arc=none smtp.client-ip=205.220.180.131
-ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
- t=1747867561; cv=none;
- b=JUfYB6YNOea3E6luldlHf63eW7OUVXEtawJXGCeH7nt9iIJpG0ODfz3v+Zl+gtQtUZ1ELh/UAhCubbThHH30w661eEN5+cQarbiqdd1cN5dnkAsmZUNSD6l//QpurFV6Wsvv4Nr2fYgyuAVHf9JDoITZKNEbIki68J7WTV+fieU=
-ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
- s=arc-20240116; t=1747867561; c=relaxed/simple;
- bh=e6/wBkUC5dKwNLeEqNLmC/3pJt4EcGfxZRx+zntD5Ek=;
- h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:
- MIME-Version:Content-Type;
- b=bg3Y4gdyPqhSKZtqqeN+SjMvTgg+BVUsyqAvkS3YPjV+C7dPwxcByNFjDRsuBqwHuSvgolo2ISExqyfJkgT6Flp4H+hriFJHcMdI0WmDf9NrBPI+E07JvNLDvP5X59C6pSrqpjXYngUV6AvPCJL7ynVBFF80h0neCm0IRu8Ur8w=
-ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
- dmarc=pass (p=none dis=none) header.from=quicinc.com;
- spf=pass smtp.mailfrom=quicinc.com;
- header.b=LbIprPEi; arc=none smtp.client-ip=205.220.180.131
-Authentication-Results: smtp.subspace.kernel.org;
- dmarc=pass (p=none dis=none) header.from=quicinc.com
-Authentication-Results: smtp.subspace.kernel.org;
- spf=pass smtp.mailfrom=quicinc.com
-Authentication-Results: smtp.subspace.kernel.org;
- header.b="LbIprPEi"
-Received: from pps.filterd (m0279873.ppops.net [127.0.0.1])
- by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id
- 54LIdAVE024983;
- Wed, 21 May 2025 22:45:54 GMT
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=
- cc:content-transfer-encoding:content-type:date:from:in-reply-to
- :message-id:mime-version:references:subject:to; s=qcppdkim1; bh=
- oR9JZ4DE7PwiZ/DcP72BpK9yTZspsBeRbWSrP3w24nY=; b=LbIprPEif55TZs6Z
- ZsvTaIhFDxESbkxn/avX548dzh51JY3wFWHowpcPEnJJdIE1oNPWkxrPo0hHkyUb
- UICPtIHoZHdMwN/uHPyglzBnBLNP82LGLHZI5eHx6jVz4INyCFm1Gmof8YNLLIo/
- pTKj4Qx3OO0jH6zSnAoKIIg39v5TWetjVZbL2qbNR+GImD0RtoefBQxRgyJWn11r
- O3ycFAW9xlW8wYJql07vue+hM3MWNtk5EPqF70c7JrrmMAYvTyOFuP0Kaf11szIB
- mF4bMyb+bb1/QA6moW7LDIoDBWEjCLINcTdGUPTnwnfBWlxZJhZoMqzU9ZuZgvsR
- 1UjthA==
-Received: from nalasppmta05.qualcomm.com (Global_NAT1.qualcomm.com
- [129.46.96.20])
- by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwf4vc5x-1
- (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
- Wed, 21 May 2025 22:45:54 +0000 (GMT)
-Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com
- [10.47.209.196])
- by NALASPPMTA05.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id
- 54LMjrWL023291
- (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
- Wed, 21 May 2025 22:45:53 GMT
-Received: from ath12k-linux2.qualcomm.com (10.80.80.8) by
- nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server
- (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
- 15.2.1544.9; Wed, 21 May 2025 15:45:52 -0700
- Pradeep Kumar Chitrapu
- "Jeff
-Subject: [PATCH ath-next V14 4/9] wifi: ath12k: generate rx and tx mcs maps
- for supported HE mcs
-Date: Wed, 21 May 2025 15:45:34 -0700
-X-Mailer: git-send-email 2.43.0
-Precedence: bulk
-List-Id: <linux-wireless.vger.kernel.org>
-MIME-Version: 1.0
-X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To
- nalasex01a.na.qualcomm.com (10.47.209.196)
-X-QCInternal: smtphost
-X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800
- signatures=585085
-X-Proofpoint-GUID: mYgnUwiU6CWGXCKmK4mo491eQG1yf62Y
-X-Proofpoint-ORIG-GUID: mYgnUwiU6CWGXCKmK4mo491eQG1yf62Y
-X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIxMDIyNiBTYWx0ZWRfX1nkoUF8smaXX
- IWIOVUfe7hMPdAVBJy7J1imFvumQnVaEdoZ98Hgv5FTjeK2Ebgl2R2fohvg1z4LsyCLnU8qfg96
- 1OdC0+PM8u7DhRIEnk7H2EZt0UJoJRxlc7daiIvimTjbBLu53yfgzses5Gth0zLCzoih5ffW/H5
- 1h2tf1ZE4W6AmHjQJc+WE0P3RhBMdl286VT/kc0ko03He0+5/QdxsynqL2e4svB4f3035pzXOEK
- dUS4nBFSZJXuBkq0d//SizRJgH9egq51A/OVPm8om04qEcOK3x9OmrrborAen5I0iuLaqAMMBXa
- nlUKQ4fpPRovjAByevo6BIIwB698Nmo72bZcFiWOocONR92lAssB6pFXJnuwOC6VQ7MJE7DKc0x
- 5UnlyGSMzMAM7cQXuGFk1AK16e6Tu/rC5YA6A4ogDKajrcBGepxGFKcZ+xK4+BwuwgI4Qysv
-X-Authority-Analysis: v=2.4 cv=R7UDGcRX c=1 sm=1 tr=0 ts=682e57a2 cx=c_pps
- a=ouPCqIW2jiPt+lZRy3xVPw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17
- a=GEpy-HfZoHoA:10 a=dt9VzEwgFbYA:10 a=COk6AnOGAAAA:8 a=WmtfbAKxhnfIJFSrnnQA:9
- a=TjNXssC_j7lpFel5tvFf:22
-X-Proofpoint-Virus-Version: vendor=baseguard
- engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40
- definitions=2025-05-21_07,2025-05-20_03,2025-03-28_01
-X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0
- phishscore=0 clxscore=1015 mlxlogscore=999 priorityscore=1501 spamscore=0
- bulkscore=0 lowpriorityscore=0 malwarescore=0 suspectscore=0 mlxscore=0
- impostorscore=0 adultscore=0 classifier=spam authscore=0 authtc=n/a authcc=
- route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2505160000
- definitions=main-2505210226
-
-Generate rx and tx mcs maps in ath12k_mac_set_hemcsmap() based
-on number of supported tx/rx chains and set them in supported
-mcs/nss for HE capabilities.
-
-Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
-
----
- drivers/net/wireless/ath/ath12k/mac.c | 40 ++++++++++++++++++++-------
- 1 file changed, 30 insertions(+), 10 deletions(-)
-
---- a/drivers/net/wireless/ath/ath12k/mac.c
-+++ b/drivers/net/wireless/ath/ath12k/mac.c
-@@ -7339,20 +7339,40 @@ static __le16 ath12k_mac_setup_he_6ghz_c
- return cpu_to_le16(bcap->he_6ghz_capa);
- }
-
--static void ath12k_mac_set_hemcsmap(struct ath12k_band_cap *band_cap,
-+static void ath12k_mac_set_hemcsmap(struct ath12k *ar,
-+ struct ath12k_pdev_cap *cap,
- struct ieee80211_sta_he_cap *he_cap)
- {
- struct ieee80211_he_mcs_nss_supp *mcs_nss = &he_cap->he_mcs_nss_supp;
-+ u16 txmcs_map, rxmcs_map;
-+ u32 i;
-
-- mcs_nss->rx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
-- mcs_nss->tx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
-- mcs_nss->rx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
-- mcs_nss->tx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
-- mcs_nss->rx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
-- mcs_nss->tx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
-+ rxmcs_map = 0;
-+ txmcs_map = 0;
-+ for (i = 0; i < 8; i++) {
-+ if (i < ar->num_tx_chains &&
-+ (ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
-+ txmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
-+ else
-+ txmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
-+
-+ if (i < ar->num_rx_chains &&
-+ (ar->cfg_rx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
-+ rxmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
-+ else
-+ rxmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
-+ }
-+
-+ mcs_nss->rx_mcs_80 = cpu_to_le16(rxmcs_map & 0xffff);
-+ mcs_nss->tx_mcs_80 = cpu_to_le16(txmcs_map & 0xffff);
-+ mcs_nss->rx_mcs_160 = cpu_to_le16(rxmcs_map & 0xffff);
-+ mcs_nss->tx_mcs_160 = cpu_to_le16(txmcs_map & 0xffff);
-+ mcs_nss->rx_mcs_80p80 = cpu_to_le16(rxmcs_map & 0xffff);
-+ mcs_nss->tx_mcs_80p80 = cpu_to_le16(txmcs_map & 0xffff);
- }
-
--static void ath12k_mac_copy_he_cap(struct ath12k_band_cap *band_cap,
-+static void ath12k_mac_copy_he_cap(struct ath12k *ar,
-+ struct ath12k_band_cap *band_cap,
- int iftype, u8 num_tx_chains,
- struct ieee80211_sta_he_cap *he_cap)
- {
-@@ -7396,7 +7416,7 @@ static void ath12k_mac_copy_he_cap(struc
- break;
- }
-
-- ath12k_mac_set_hemcsmap(band_cap, he_cap);
-+ ath12k_mac_set_hemcsmap(ar, &ar->pdev->cap, he_cap);
- memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
- if (he_cap_elem->phy_cap_info[6] &
- IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)
-@@ -7586,7 +7606,7 @@ static int ath12k_mac_copy_sband_iftype_
-
- data[idx].types_mask = BIT(i);
-
-- ath12k_mac_copy_he_cap(band_cap, i, ar->num_tx_chains, he_cap);
-+ ath12k_mac_copy_he_cap(ar, band_cap, i, ar->num_tx_chains, he_cap);
- if (band == NL80211_BAND_6GHZ) {
- data[idx].he_6ghz_capa.capa =
- ath12k_mac_setup_he_6ghz_cap(cap, band_cap);
+++ /dev/null
-From patchwork Wed May 21 22:45:35 2025
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Id: 14096120
-Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com
- [205.220.180.131])
- (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
- (No client certificate requested)
- by smtp.subspace.kernel.org (Postfix) with ESMTPS id A3B9F239570
-Authentication-Results: smtp.subspace.kernel.org;
- arc=none smtp.client-ip=205.220.180.131
-ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
- t=1747867560; cv=none;
- b=GmlOnDZdpnT/77kfeg7qPbZIn+pp+Rv41/WYnHylPZroDHwpWp5rzjObHMVoVIVB8f5dpHJSWNb5ucf0EdCqAqynnnDnAHne0d3j8kMBBH6ZVQr4AnIsYhkIrbmy6o7JffEBF094XVxGwQTjyWSEPi6VY94Md6L1NnuF0J5lJXw=
-ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
- s=arc-20240116; t=1747867560; c=relaxed/simple;
- bh=Xdsuttpv57eTzMnRm7g3A0+frkCx/SnGj1xOjVOXHng=;
- h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:
- MIME-Version:Content-Type;
- b=DCZ4pyonUsAaIuBQUBu/1NYBINM2V/yqfV+6ngHC6I8x7PP5e0WLPB1zEyJgRG752GtXxlhP3WdI6a+eW/8O0I64lNeSLtCeGZQ2ljn0mAfcuMtjB3rZq3UejFTR8v3I78Chfhv8/eSjfW7gSO+sswpSCXiFykPgseD3Hhz6W/4=
-ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
- dmarc=pass (p=none dis=none) header.from=quicinc.com;
- spf=pass smtp.mailfrom=quicinc.com;
- header.b=n5c8p9dB; arc=none smtp.client-ip=205.220.180.131
-Authentication-Results: smtp.subspace.kernel.org;
- dmarc=pass (p=none dis=none) header.from=quicinc.com
-Authentication-Results: smtp.subspace.kernel.org;
- spf=pass smtp.mailfrom=quicinc.com
-Authentication-Results: smtp.subspace.kernel.org;
- header.b="n5c8p9dB"
-Received: from pps.filterd (m0279869.ppops.net [127.0.0.1])
- by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id
- 54LIhKMc027654;
- Wed, 21 May 2025 22:45:54 GMT
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=
- cc:content-transfer-encoding:content-type:date:from:in-reply-to
- :message-id:mime-version:references:subject:to; s=qcppdkim1; bh=
- igBIHxXxEIGErFGPWQKC8rBeF0DUPvb+tsDy6dmbEUQ=; b=n5c8p9dBo/+917ae
- iUuuRoUPhgwmxRjEorR4N5thttRSLen0XwHulOSFzfVHZvX/ZX7Xb8qa67RpJUAw
- jx3TGu38TFybZ9zCbXxa3PoR7FqIyl7TyaU+RpGmjLnDTRjq5ODiDDkcGM8aLJ6C
- pgH1JDyjAtZODpP3W+kKpoMlU/N8QCB8wVOob4E3+nH0XDeYWh0cSY4dAnFcFYsC
- dgkUoVt65T3wJptGX80bBT1muPG/3O+IiWrYoP6NVayscmgOnCqKVpuSjYrEn/02
- HlxMp7yg/I4LhlQquL2SfmAXdKThQLrOF/XiFsCW2VZETvSbXsLI0NXYRbRFUxC4
- e9SLmw==
-Received: from nalasppmta05.qualcomm.com (Global_NAT1.qualcomm.com
- [129.46.96.20])
- by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwf9cars-1
- (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
- Wed, 21 May 2025 22:45:54 +0000 (GMT)
-Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com
- [10.47.209.196])
- by NALASPPMTA05.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id
- 54LMjrc1023294
- (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
- Wed, 21 May 2025 22:45:53 GMT
-Received: from ath12k-linux2.qualcomm.com (10.80.80.8) by
- nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server
- (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
- 15.2.1544.9; Wed, 21 May 2025 15:45:53 -0700
- Pradeep Kumar Chitrapu
-Subject: [PATCH ath-next V14 5/9] wifi: ath12k: fix TX and RX MCS rate
- configurations in HE mode
-Date: Wed, 21 May 2025 15:45:35 -0700
-X-Mailer: git-send-email 2.43.0
-Precedence: bulk
-List-Id: <linux-wireless.vger.kernel.org>
-MIME-Version: 1.0
-X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To
- nalasex01a.na.qualcomm.com (10.47.209.196)
-X-QCInternal: smtphost
-X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800
- signatures=585085
-X-Proofpoint-ORIG-GUID: lrtwH7rWiPRFD03fbbD0IavLBLpNgTW-
-X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIxMDIyNSBTYWx0ZWRfX0HS2wunF/V5Q
- jQqxwakF2Imrc/4a4WgPSFOFxUyO27D7Yw6gnIBRodgtwOFgflHDfeJMrELW79jrSDvXvRC0nnc
- lTonRisd7/CZWExy3sM2diYhHrZ5YT1dPhFtq33ItpY8BaOhwiLxc3wn0tlWRX8B/cd+xyEHTZY
- A4nCDSw77SEdaZfmqAB81LMzQWIuTucnxkms4pM1CIIYZrgAPcBk4XN8tWVQ6JQKCpMpelTF6Hj
- /XLCY2ByRqjtwd/zSjtcCfLOyKdT+uQtAJU1XZvedwqQW5MFk2GeD7O72PfhAP1V0YcbHdiTxde
- roRpAlQg48k0Ug5EMIUPb9TYEP15vwtPDTw03C3u7eOhs6znDqvMYNAtXwbxfGeHRwjsbMgpWLG
- +weN3zziLWlwb66N0xo5nfdJRHrOVDNcSx8/Z/xvCmHBTuVr44Q7It0iW+CGbHNqXrg4h4CH
-X-Authority-Analysis: v=2.4 cv=GawXnRXL c=1 sm=1 tr=0 ts=682e57a2 cx=c_pps
- a=ouPCqIW2jiPt+lZRy3xVPw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17
- a=GEpy-HfZoHoA:10 a=dt9VzEwgFbYA:10 a=COk6AnOGAAAA:8 a=mu3tZSmwaZwQUXtd2tAA:9
- a=TjNXssC_j7lpFel5tvFf:22
-X-Proofpoint-GUID: lrtwH7rWiPRFD03fbbD0IavLBLpNgTW-
-X-Proofpoint-Virus-Version: vendor=baseguard
- engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40
- definitions=2025-05-21_07,2025-05-20_03,2025-03-28_01
-X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0
- mlxscore=0 mlxlogscore=999 lowpriorityscore=0 impostorscore=0
- priorityscore=1501 clxscore=1015 malwarescore=0 phishscore=0 bulkscore=0
- spamscore=0 suspectscore=0 adultscore=0 classifier=spam authscore=0
- authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1
- engine=8.19.0-2505160000 definitions=main-2505210225
-
-Currently, the TX and RX MCS rate configurations per peer are
-reversed when sent to the firmware. As a result, RX MCS rates
-are configured for TX, and vice versa. This commit rectifies
-the configuration to match what the firmware expects.
-
-Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
-
-Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
----
- drivers/net/wireless/ath/ath12k/wmi.c | 4 ++--
- drivers/net/wireless/ath/ath12k/wmi.h | 2 ++
- 2 files changed, 4 insertions(+), 2 deletions(-)
-
---- a/drivers/net/wireless/ath/ath12k/wmi.c
-+++ b/drivers/net/wireless/ath/ath12k/wmi.c
-@@ -2333,8 +2333,8 @@ int ath12k_wmi_send_peer_assoc_cmd(struc
- he_mcs->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_HE_RATE_SET,
- sizeof(*he_mcs));
-
-- he_mcs->rx_mcs_set = cpu_to_le32(arg->peer_he_rx_mcs_set[i]);
-- he_mcs->tx_mcs_set = cpu_to_le32(arg->peer_he_tx_mcs_set[i]);
-+ he_mcs->rx_mcs_set = cpu_to_le32(arg->peer_he_tx_mcs_set[i]);
-+ he_mcs->tx_mcs_set = cpu_to_le32(arg->peer_he_rx_mcs_set[i]);
- ptr += sizeof(*he_mcs);
- }
-
---- a/drivers/net/wireless/ath/ath12k/wmi.h
-+++ b/drivers/net/wireless/ath/ath12k/wmi.h
-@@ -4157,7 +4157,9 @@ struct ath12k_wmi_vht_rate_set_params {
-
- struct ath12k_wmi_he_rate_set_params {
- __le32 tlv_header;
-+ /* MCS at which the peer can receive */
- __le32 rx_mcs_set;
-+ /* MCS at which the peer can transmit */
- __le32 tx_mcs_set;
- } __packed;
-
+++ /dev/null
-From patchwork Wed May 21 22:45:36 2025
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Id: 14096125
-Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com
- [205.220.180.131])
- (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
- (No client certificate requested)
- by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9A17F1B0F20
-Authentication-Results: smtp.subspace.kernel.org;
- arc=none smtp.client-ip=205.220.180.131
-ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
- t=1747867562; cv=none;
- b=bEGfSmKJAIERqJyK0yJndcYM+a7cpfrIkMLoGUTFvAkrcwqnlh3F9AqLbcb8fKznhfaQKFVRUdpVGSjFaplFVSp20RuXvPC2NLb0eKZrz5qS/4geTMxY/BeWuVN+i3ouoQzfYz8Vq6sTqLE5d6b650cCVf8hpY+VZ3ZTNWxVvdA=
-ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
- s=arc-20240116; t=1747867562; c=relaxed/simple;
- bh=hBxlXRYYCPbv8+evEatym1UfdpOfENFUVDWgibN+XTg=;
- h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:
- MIME-Version:Content-Type;
- b=U32JKi6TAoRF/9e1cv0vPGUM6BaRhoFXM0b36j5PBpvKQmRXKDF/UNScd5EJnrFOPlgjPD7GOc+TdHqsFGk/7pNucA1++GU00SZ0q/223zg5dCsYLmfLrRu3G22WZS2hWuNKuUPFJEFFLEJ8UQWKtFB0oWsQcx+Oj1mWPbBrDU8=
-ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
- dmarc=pass (p=none dis=none) header.from=quicinc.com;
- spf=pass smtp.mailfrom=quicinc.com;
- header.b=bzVTzUcl; arc=none smtp.client-ip=205.220.180.131
-Authentication-Results: smtp.subspace.kernel.org;
- dmarc=pass (p=none dis=none) header.from=quicinc.com
-Authentication-Results: smtp.subspace.kernel.org;
- spf=pass smtp.mailfrom=quicinc.com
-Authentication-Results: smtp.subspace.kernel.org;
- header.b="bzVTzUcl"
-Received: from pps.filterd (m0279868.ppops.net [127.0.0.1])
- by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id
- 54LJiK6V032422;
- Wed, 21 May 2025 22:45:55 GMT
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=
- cc:content-transfer-encoding:content-type:date:from:in-reply-to
- :message-id:mime-version:references:subject:to; s=qcppdkim1; bh=
- cpcIGD4iPSOaZzDkHZpoGs5Kor0sF3EnocHYcBOazgM=; b=bzVTzUclt3RkLn9A
- YI8+MC64RjF5llUqmQ0G53D8sAQZ+95fc92X/ZrZvnyr7X0FBI+gU05yKzNuv4M5
- XcIWK7Y8gjr55i9w18cWHGW2Q/JGC8pJlx0A/SEAMIMXeeEmgJqdKowT2wMjzIIH
- wb7JmE9d6z6ZKcgQYx9KICXaaEFQ9uxyRyjlJMMEJ3zb7MjxZPCCGtCI31Aqczpk
- B3X+1UgRT+OJzV6vIF0kdn/sjU69iZNHoPAUDYqInWCs2lPLMUO5mckhOG3fH8s6
- jmhgpwlpUYx18jawRUpklvujXfFiDV4daXLeUKzL5b08f5OcSRvd7+iOytudYgr0
- U9VYkw==
-Received: from nalasppmta03.qualcomm.com (Global_NAT1.qualcomm.com
- [129.46.96.20])
- by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwfb4b3w-1
- (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
- Wed, 21 May 2025 22:45:55 +0000 (GMT)
-Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com
- [10.47.209.196])
- by NALASPPMTA03.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id
- 54LMjsC2027097
- (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
- Wed, 21 May 2025 22:45:54 GMT
-Received: from ath12k-linux2.qualcomm.com (10.80.80.8) by
- nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server
- (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
- 15.2.1544.9; Wed, 21 May 2025 15:45:53 -0700
- Pradeep Kumar Chitrapu
-Subject: [PATCH ath-next V14 6/9] wifi: ath12k: add support for setting fixed
- HE rate/GI/LTF
-Date: Wed, 21 May 2025 15:45:36 -0700
-X-Mailer: git-send-email 2.43.0
-Precedence: bulk
-List-Id: <linux-wireless.vger.kernel.org>
-MIME-Version: 1.0
-X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To
- nalasex01a.na.qualcomm.com (10.47.209.196)
-X-QCInternal: smtphost
-X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800
- signatures=585085
-X-Proofpoint-ORIG-GUID: 7uuxK_kl_b0JzKZoWIyq_ZYKeKL3it15
-X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIxMDIyNiBTYWx0ZWRfX7sjoM15po0tB
- FcR1nwzr8TocaDYnIXgl13rA+kjwsizlMt/N5cu8dCWo9YQKqFNy42Z2VEYmoDRw7dBnYnsMIL/
- wwv4hQYQslnxilRJaX/MVQ50/xxhSry8NrKA2QXvIg3btmiW4gQfrn3+k1Rm3o/gAGv2Yz4R8lw
- YBPHVdQkgGJXYgsiB/b+copbnU621GYiYrCW6yUQHHIiwzjMljzzsk+9Koc6yeVByyPj86P80y7
- 2C8L1vuRAy8gCMSScMB9CyQ6+tLCKa1W2bhA0Oxz/+RGEXbujS4NDXCWz+EqIaYS5HXuD32pODy
- O2wMURrbgE5PJIjjvpAdtqZL65QVaoVK1LWU6Co0NtHytEjuaZmr1hbb4hVDAtQio2Bw/K8yCM+
- ikcJ1sGkE78mu/U7gQjG6g0Z71Q/w13jBOz+RIocPFi2FyEjy5KDFmUBzY+jDCIRLi06R8sP
-X-Proofpoint-GUID: 7uuxK_kl_b0JzKZoWIyq_ZYKeKL3it15
-X-Authority-Analysis: v=2.4 cv=dLCmmPZb c=1 sm=1 tr=0 ts=682e57a3 cx=c_pps
- a=ouPCqIW2jiPt+lZRy3xVPw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17
- a=GEpy-HfZoHoA:10 a=dt9VzEwgFbYA:10 a=COk6AnOGAAAA:8 a=KygRlO7-s-l5tpycOzUA:9
- a=TjNXssC_j7lpFel5tvFf:22
-X-Proofpoint-Virus-Version: vendor=baseguard
- engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40
- definitions=2025-05-21_07,2025-05-20_03,2025-03-28_01
-X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0
- mlxscore=0 clxscore=1015 adultscore=0 bulkscore=0 phishscore=0 suspectscore=0
- impostorscore=0 malwarescore=0 lowpriorityscore=0 mlxlogscore=999 spamscore=0
- priorityscore=1501 classifier=spam authscore=0 authtc=n/a authcc=
- route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2505160000
- definitions=main-2505210226
-
-Add support to set fixed HE rate/GI/LTF values using nl80211.
-Reuse parts of the existing code path already used for HT/VHT
-to implement the new helpers symmetrically, similar to how
-HT/VHT is handled.
-
-Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
-
----
- drivers/net/wireless/ath/ath12k/mac.c | 650 +++++++++++++++++++++++---
- drivers/net/wireless/ath/ath12k/wmi.h | 27 ++
- 2 files changed, 625 insertions(+), 52 deletions(-)
-
---- a/drivers/net/wireless/ath/ath12k/mac.c
-+++ b/drivers/net/wireless/ath/ath12k/mac.c
-@@ -521,6 +521,18 @@ ath12k_mac_max_vht_nss(const u16 *vht_mc
- return 1;
- }
-
-+static u32
-+ath12k_mac_max_he_nss(const u16 he_mcs_mask[NL80211_HE_NSS_MAX])
-+{
-+ int nss;
-+
-+ for (nss = NL80211_HE_NSS_MAX - 1; nss >= 0; nss--)
-+ if (he_mcs_mask[nss])
-+ return nss + 1;
-+
-+ return 1;
-+}
-+
- static u8 ath12k_parse_mpdudensity(u8 mpdudensity)
- {
- /* From IEEE Std 802.11-2020 defined values for "Minimum MPDU Start Spacing":
-@@ -2053,9 +2065,15 @@ static void ath12k_peer_assoc_h_ht(struc
- arg->peer_rate_caps |= WMI_HOST_RC_CW40_FLAG;
- }
-
-- if (arvif->bitrate_mask.control[band].gi != NL80211_TXRATE_FORCE_LGI) {
-- if (ht_cap->cap & (IEEE80211_HT_CAP_SGI_20 |
-- IEEE80211_HT_CAP_SGI_40))
-+ /* As firmware handles these two flags (IEEE80211_HT_CAP_SGI_20
-+ * and IEEE80211_HT_CAP_SGI_40) for enabling SGI, reset both
-+ * flags if guard interval is to force Long GI
-+ */
-+ if (arvif->bitrate_mask.control[band].gi == NL80211_TXRATE_FORCE_LGI) {
-+ arg->peer_ht_caps &= ~(IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40);
-+ } else {
-+ /* Enable SGI flag if either SGI_20 or SGI_40 is supported */
-+ if (ht_cap->cap & (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40))
- arg->peer_rate_caps |= WMI_HOST_RC_SGI_FLAG;
- }
-
-@@ -2178,11 +2196,12 @@ static void ath12k_peer_assoc_h_vht(stru
- struct ieee80211_link_sta *link_sta;
- struct cfg80211_chan_def def;
- enum nl80211_band band;
-- const u16 *vht_mcs_mask;
-+ u16 *vht_mcs_mask;
- u16 tx_mcs_map;
- u8 ampdu_factor;
- u8 max_nss, vht_mcs;
-- int i;
-+ int i, vht_nss, nss_idx;
-+ bool user_rate_valid = true;
-
- lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
-
-@@ -2235,6 +2254,25 @@ static void ath12k_peer_assoc_h_vht(stru
- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160)
- arg->bw_160 = true;
-
-+ vht_nss = ath12k_mac_max_vht_nss(vht_mcs_mask);
-+
-+ if (vht_nss > link_sta->rx_nss) {
-+ user_rate_valid = false;
-+ for (nss_idx = link_sta->rx_nss - 1; nss_idx >= 0; nss_idx--) {
-+ if (vht_mcs_mask[nss_idx]) {
-+ user_rate_valid = true;
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (!user_rate_valid) {
-+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
-+ "Setting vht range MCS value to peer supported nss:%d for peer %pM\n",
-+ link_sta->rx_nss, arsta->addr);
-+ vht_mcs_mask[link_sta->rx_nss - 1] = vht_mcs_mask[vht_nss - 1];
-+ }
-+
- /* Calculate peer NSS capability from VHT capabilities if STA
- * supports VHT.
- */
-@@ -2274,6 +2312,72 @@ static void ath12k_peer_assoc_h_vht(stru
- /* TODO: rxnss_override */
- }
-
-+static int ath12k_mac_get_max_he_mcs_map(u16 mcs_map, int nss)
-+{
-+ switch ((mcs_map >> (2 * nss)) & 0x3) {
-+ case IEEE80211_HE_MCS_SUPPORT_0_7: return BIT(8) - 1;
-+ case IEEE80211_HE_MCS_SUPPORT_0_9: return BIT(10) - 1;
-+ case IEEE80211_HE_MCS_SUPPORT_0_11: return BIT(12) - 1;
-+ }
-+ return 0;
-+}
-+
-+static u16 ath12k_peer_assoc_h_he_limit(u16 tx_mcs_set,
-+ const u16 *he_mcs_limit)
-+{
-+ int idx_limit;
-+ int nss;
-+ u16 mcs_map;
-+ u16 mcs;
-+
-+ for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) {
-+ mcs_map = ath12k_mac_get_max_he_mcs_map(tx_mcs_set, nss) &
-+ he_mcs_limit[nss];
-+
-+ if (mcs_map)
-+ idx_limit = fls(mcs_map) - 1;
-+ else
-+ idx_limit = -1;
-+
-+ switch (idx_limit) {
-+ case 0 ... 7:
-+ mcs = IEEE80211_HE_MCS_SUPPORT_0_7;
-+ break;
-+ case 8:
-+ case 9:
-+ mcs = IEEE80211_HE_MCS_SUPPORT_0_9;
-+ break;
-+ case 10:
-+ case 11:
-+ mcs = IEEE80211_HE_MCS_SUPPORT_0_11;
-+ break;
-+ default:
-+ WARN_ON(1);
-+ fallthrough;
-+ case -1:
-+ mcs = IEEE80211_HE_MCS_NOT_SUPPORTED;
-+ break;
-+ }
-+
-+ tx_mcs_set &= ~(0x3 << (nss * 2));
-+ tx_mcs_set |= mcs << (nss * 2);
-+ }
-+
-+ return tx_mcs_set;
-+}
-+
-+static bool
-+ath12k_peer_assoc_h_he_masked(const u16 he_mcs_mask[NL80211_HE_NSS_MAX])
-+{
-+ int nss;
-+
-+ for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++)
-+ if (he_mcs_mask[nss])
-+ return false;
-+
-+ return true;
-+}
-+
- static void ath12k_peer_assoc_h_he(struct ath12k *ar,
- struct ath12k_link_vif *arvif,
- struct ath12k_link_sta *arsta,
-@@ -2284,18 +2388,28 @@ static void ath12k_peer_assoc_h_he(struc
- const struct ieee80211_sta_he_cap *he_cap;
- struct ieee80211_bss_conf *link_conf;
- struct ieee80211_link_sta *link_sta;
-+ struct cfg80211_chan_def def;
- int i;
- u8 ampdu_factor, max_nss;
- u8 rx_mcs_80 = IEEE80211_HE_MCS_NOT_SUPPORTED;
- u8 rx_mcs_160 = IEEE80211_HE_MCS_NOT_SUPPORTED;
- u16 mcs_160_map, mcs_80_map;
-+ u8 link_id = arvif->link_id;
- bool support_160;
-- u16 v;
-+ enum nl80211_band band;
-+ u16 *he_mcs_mask;
-+ u8 he_mcs;
-+ u16 he_tx_mcs = 0, v = 0;
-+ int he_nss, nss_idx;
-+ bool user_rate_valid = true;
-+
-+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, link_id, &def)))
-+ return;
-
- link_conf = ath12k_mac_get_link_bss_conf(arvif);
- if (!link_conf) {
- ath12k_warn(ar->ab, "unable to access bss link conf in peer assoc he for vif %pM link %u",
-- vif->addr, arvif->link_id);
-+ vif->addr, link_id);
- return;
- }
-
-@@ -2310,6 +2424,12 @@ static void ath12k_peer_assoc_h_he(struc
- if (!he_cap->has_he)
- return;
-
-+ band = def.chan->band;
-+ he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs;
-+
-+ if (ath12k_peer_assoc_h_he_masked(he_mcs_mask))
-+ return;
-+
- arg->he_flag = true;
-
- support_160 = !!(he_cap->he_cap_elem.phy_cap_info[0] &
-@@ -2415,25 +2535,47 @@ static void ath12k_peer_assoc_h_he(struc
- if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_REQ)
- arg->twt_requester = true;
-
-+ he_nss = ath12k_mac_max_he_nss(he_mcs_mask);
-+
-+ if (he_nss > link_sta->rx_nss) {
-+ user_rate_valid = false;
-+ for (nss_idx = link_sta->rx_nss - 1; nss_idx >= 0; nss_idx--) {
-+ if (he_mcs_mask[nss_idx]) {
-+ user_rate_valid = true;
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (!user_rate_valid) {
-+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
-+ "Setting he range MCS value to peer supported nss:%d for peer %pM\n",
-+ link_sta->rx_nss, arsta->addr);
-+ he_mcs_mask[link_sta->rx_nss - 1] = he_mcs_mask[he_nss - 1];
-+ }
-+
- switch (link_sta->bandwidth) {
- case IEEE80211_STA_RX_BW_160:
- if (he_cap->he_cap_elem.phy_cap_info[0] &
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) {
-- v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80p80);
-+ v = ath12k_peer_assoc_h_he_limit(v, he_mcs_mask);
- arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
-
- v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80p80);
- arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
-
- arg->peer_he_mcs_count++;
-+ he_tx_mcs = v;
- }
- v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
- arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
-
-- v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_160);
-+ v = ath12k_peer_assoc_h_he_limit(v, he_mcs_mask);
- arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
-
- arg->peer_he_mcs_count++;
-+ if (!he_tx_mcs)
-+ he_tx_mcs = v;
- fallthrough;
-
- default:
-@@ -2441,11 +2583,36 @@ static void ath12k_peer_assoc_h_he(struc
- arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
-
- v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80);
-+ v = ath12k_peer_assoc_h_he_limit(v, he_mcs_mask);
- arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
-
- arg->peer_he_mcs_count++;
-+ if (!he_tx_mcs)
-+ he_tx_mcs = v;
- break;
- }
-+
-+ /* Calculate peer NSS capability from HE capabilities if STA
-+ * supports HE.
-+ */
-+ for (i = 0, max_nss = 0, he_mcs = 0; i < NL80211_HE_NSS_MAX; i++) {
-+ he_mcs = he_tx_mcs >> (2 * i) & 3;
-+
-+ /* In case of fixed rates, MCS Range in he_tx_mcs might have
-+ * unsupported range, with he_mcs_mask set, so check either of them
-+ * to find nss.
-+ */
-+ if (he_mcs != IEEE80211_HE_MCS_NOT_SUPPORTED ||
-+ he_mcs_mask[i])
-+ max_nss = i + 1;
-+ }
-+
-+ max_nss = min(max_nss, ar->num_tx_chains);
-+ arg->peer_nss = min(link_sta->rx_nss, max_nss);
-+
-+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
-+ "mac he peer %pM nss %d mcs cnt %d\n",
-+ arsta->addr, arg->peer_nss, arg->peer_he_mcs_count);
- }
-
- static void ath12k_peer_assoc_h_he_6ghz(struct ath12k *ar,
-@@ -2781,6 +2948,7 @@ static void ath12k_peer_assoc_h_phymode(
- enum nl80211_band band;
- const u8 *ht_mcs_mask;
- const u16 *vht_mcs_mask;
-+ const u16 *he_mcs_mask;
- enum wmi_phy_mode phymode = MODE_UNKNOWN;
-
- lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
-@@ -2794,6 +2962,7 @@ static void ath12k_peer_assoc_h_phymode(
- band = def.chan->band;
- ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
- vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
-+ he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs;
-
- link_sta = ath12k_mac_get_link_sta(arsta);
- if (!link_sta) {
-@@ -2809,7 +2978,8 @@ static void ath12k_peer_assoc_h_phymode(
- phymode = MODE_11BE_EHT40_2G;
- else
- phymode = MODE_11BE_EHT20_2G;
-- } else if (link_sta->he_cap.has_he) {
-+ } else if (link_sta->he_cap.has_he &&
-+ !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) {
- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80)
- phymode = MODE_11AX_HE80_2G;
- else if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40)
-@@ -2839,7 +3009,8 @@ static void ath12k_peer_assoc_h_phymode(
- /* Check EHT first */
- if (link_sta->eht_cap.has_eht) {
- phymode = ath12k_mac_get_phymode_eht(ar, link_sta);
-- } else if (link_sta->he_cap.has_he) {
-+ } else if (link_sta->he_cap.has_he &&
-+ !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) {
- phymode = ath12k_mac_get_phymode_he(ar, link_sta);
- } else if (link_sta->vht_cap.vht_supported &&
- !ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
-@@ -3623,10 +3794,13 @@ static void ath12k_mac_init_arvif(struct
-
- for (i = 0; i < ARRAY_SIZE(arvif->bitrate_mask.control); i++) {
- arvif->bitrate_mask.control[i].legacy = 0xffffffff;
-+ arvif->bitrate_mask.control[i].gi = NL80211_TXRATE_DEFAULT_GI;
- memset(arvif->bitrate_mask.control[i].ht_mcs, 0xff,
- sizeof(arvif->bitrate_mask.control[i].ht_mcs));
- memset(arvif->bitrate_mask.control[i].vht_mcs, 0xff,
- sizeof(arvif->bitrate_mask.control[i].vht_mcs));
-+ memset(arvif->bitrate_mask.control[i].he_mcs, 0xff,
-+ sizeof(arvif->bitrate_mask.control[i].he_mcs));
- }
-
- /* Handle MLO related assignments */
-@@ -5282,6 +5456,20 @@ ath12k_mac_bitrate_mask_num_vht_rates(st
- }
-
- static int
-+ath12k_mac_bitrate_mask_num_he_rates(struct ath12k *ar,
-+ enum nl80211_band band,
-+ const struct cfg80211_bitrate_mask *mask)
-+{
-+ int num_rates = 0;
-+ int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++)
-+ num_rates += hweight16(mask->control[band].he_mcs[i]);
-+
-+ return num_rates;
-+}
-+
-+static int
- ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_link_vif *arvif,
- struct ath12k_link_sta *arsta,
- const struct cfg80211_bitrate_mask *mask,
-@@ -5327,6 +5515,60 @@ ath12k_mac_set_peer_vht_fixed_rate(struc
- return ret;
- }
-
-+static int
-+ath12k_mac_set_peer_he_fixed_rate(struct ath12k_link_vif *arvif,
-+ struct ath12k_link_sta *arsta,
-+ const struct cfg80211_bitrate_mask *mask,
-+ enum nl80211_band band)
-+{
-+ struct ath12k *ar = arvif->ar;
-+ u8 he_rate, nss;
-+ u32 rate_code;
-+ int ret, i;
-+ struct ath12k_sta *ahsta = arsta->ahsta;
-+ struct ieee80211_sta *sta;
-+
-+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
-+
-+ sta = ath12k_ahsta_to_sta(ahsta);
-+ nss = 0;
-+
-+ for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++) {
-+ if (hweight16(mask->control[band].he_mcs[i]) == 1) {
-+ nss = i + 1;
-+ he_rate = ffs(mask->control[band].he_mcs[i]) - 1;
-+ }
-+ }
-+
-+ if (!nss) {
-+ ath12k_warn(ar->ab, "No single HE Fixed rate found to set for %pM",
-+ arsta->addr);
-+ return -EINVAL;
-+ }
-+
-+ /* Avoid updating invalid nss as fixed rate*/
-+ if (nss > sta->deflink.rx_nss)
-+ return -EINVAL;
-+
-+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
-+ "Setting Fixed HE Rate for peer %pM. Device will not switch to any other selected rates",
-+ arsta->addr);
-+
-+ rate_code = ATH12K_HW_RATE_CODE(he_rate, nss - 1,
-+ WMI_RATE_PREAMBLE_HE);
-+
-+ ret = ath12k_wmi_set_peer_param(ar, arsta->addr,
-+ arvif->vdev_id,
-+ WMI_PEER_PARAM_FIXED_RATE,
-+ rate_code);
-+ if (ret)
-+ ath12k_warn(ar->ab,
-+ "failed to update STA %pM Fixed Rate %d: %d\n",
-+ arsta->addr, rate_code, ret);
-+
-+ return ret;
-+}
-+
- static int ath12k_mac_station_assoc(struct ath12k *ar,
- struct ath12k_link_vif *arvif,
- struct ath12k_link_sta *arsta,
-@@ -5339,7 +5581,7 @@ static int ath12k_mac_station_assoc(stru
- struct cfg80211_chan_def def;
- enum nl80211_band band;
- struct cfg80211_bitrate_mask *mask;
-- u8 num_vht_rates;
-+ u8 num_vht_rates, num_he_rates;
- u8 link_id = arvif->link_id;
-
- lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
-@@ -5379,9 +5621,10 @@ static int ath12k_mac_station_assoc(stru
- }
-
- num_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask);
-+ num_he_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask);
-
-- /* If single VHT rate is configured (by set_bitrate_mask()),
-- * peer_assoc will disable VHT. This is now enabled by a peer specific
-+ /* If single VHT/HE rate is configured (by set_bitrate_mask()),
-+ * peer_assoc will disable VHT/HE. This is now enabled by a peer specific
- * fixed param.
- * Note that all other rates and NSS will be disabled for this peer.
- */
-@@ -5397,8 +5640,9 @@ static int ath12k_mac_station_assoc(stru
- spin_unlock_bh(&ar->data_lock);
-
- if (link_sta->vht_cap.vht_supported && num_vht_rates == 1) {
-- ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask,
-- band);
-+ ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask, band);
-+ } else if (link_sta->he_cap.has_he && num_he_rates == 1) {
-+ ret = ath12k_mac_set_peer_he_fixed_rate(arvif, arsta, mask, band);
- if (ret)
- return ret;
- }
-@@ -5462,8 +5706,9 @@ static void ath12k_sta_rc_update_wk(stru
- enum nl80211_band band;
- const u8 *ht_mcs_mask;
- const u16 *vht_mcs_mask;
-- u32 changed, bw, nss, smps, bw_prev;
-- int err, num_vht_rates;
-+ const u16 *he_mcs_mask;
-+ u32 changed, bw, nss, mac_nss, smps, bw_prev;
-+ int err, num_vht_rates, num_he_rates;
- const struct cfg80211_bitrate_mask *mask;
- enum wmi_phy_mode peer_phymode;
- struct ath12k_link_sta *arsta;
-@@ -5483,6 +5728,7 @@ static void ath12k_sta_rc_update_wk(stru
- band = def.chan->band;
- ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
- vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
-+ he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs;
-
- spin_lock_bh(&ar->data_lock);
-
-@@ -5497,8 +5743,10 @@ static void ath12k_sta_rc_update_wk(stru
- spin_unlock_bh(&ar->data_lock);
-
- nss = max_t(u32, 1, nss);
-- nss = min(nss, max(ath12k_mac_max_ht_nss(ht_mcs_mask),
-- ath12k_mac_max_vht_nss(vht_mcs_mask)));
-+ mac_nss = max3(ath12k_mac_max_ht_nss(ht_mcs_mask),
-+ ath12k_mac_max_vht_nss(vht_mcs_mask),
-+ ath12k_mac_max_he_nss(he_mcs_mask));
-+ nss = min(nss, mac_nss);
-
- struct ath12k_wmi_peer_assoc_arg *peer_arg __free(kfree) =
- kzalloc(sizeof(*peer_arg), GFP_KERNEL);
-@@ -5581,6 +5829,8 @@ static void ath12k_sta_rc_update_wk(stru
- mask = &arvif->bitrate_mask;
- num_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band,
- mask);
-+ num_he_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band,
-+ mask);
-
- /* Peer_assoc_prepare will reject vht rates in
- * bitrate_mask if its not available in range format and
-@@ -5603,11 +5853,24 @@ static void ath12k_sta_rc_update_wk(stru
- if (link_sta->vht_cap.vht_supported && num_vht_rates == 1) {
- ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask,
- band);
-+ } else if (link_sta->he_cap.has_he && num_he_rates == 1) {
-+ ath12k_mac_set_peer_he_fixed_rate(arvif, arsta, mask, band);
- } else {
-- /* If the peer is non-VHT or no fixed VHT rate
-+ /* If the peer is non-VHT/HE or no fixed VHT/HE rate
- * is provided in the new bitrate mask we set the
-- * other rates using peer_assoc command.
-+ * other rates using peer_assoc command. Also clear
-+ * the peer fixed rate settings as it has higher proprity
-+ * than peer assoc
- */
-+ err = ath12k_wmi_set_peer_param(ar, arsta->addr,
-+ arvif->vdev_id,
-+ WMI_PEER_PARAM_FIXED_RATE,
-+ WMI_FIXED_RATE_NONE);
-+ if (err)
-+ ath12k_warn(ar->ab,
-+ "failed to disable peer fixed rate for STA %pM ret %d\n",
-+ arsta->addr, err);
-+
- ath12k_peer_assoc_prepare(ar, arvif, arsta,
- peer_arg, true);
-
-@@ -11036,19 +11299,40 @@ ath12k_mac_has_single_legacy_rate(struct
- if (ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask))
- return false;
-
-+ if (ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask))
-+ return false;
-+
- return num_rates == 1;
- }
-
-+static __le16
-+ath12k_mac_get_tx_mcs_map(const struct ieee80211_sta_he_cap *he_cap)
-+{
-+ if (he_cap->he_cap_elem.phy_cap_info[0] &
-+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
-+ return he_cap->he_mcs_nss_supp.tx_mcs_80p80;
-+
-+ if (he_cap->he_cap_elem.phy_cap_info[0] &
-+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
-+ return he_cap->he_mcs_nss_supp.tx_mcs_160;
-+
-+ return he_cap->he_mcs_nss_supp.tx_mcs_80;
-+}
-+
- static bool
- ath12k_mac_bitrate_mask_get_single_nss(struct ath12k *ar,
-+ struct ieee80211_vif *vif,
- enum nl80211_band band,
- const struct cfg80211_bitrate_mask *mask,
- int *nss)
- {
- struct ieee80211_supported_band *sband = &ar->mac.sbands[band];
- u16 vht_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
-+ const struct ieee80211_sta_he_cap *he_cap;
-+ u16 he_mcs_map = 0;
- u8 ht_nss_mask = 0;
- u8 vht_nss_mask = 0;
-+ u8 he_nss_mask = 0;
- int i;
-
- /* No need to consider legacy here. Basic rates are always present
-@@ -11075,7 +11359,24 @@ ath12k_mac_bitrate_mask_get_single_nss(s
- return false;
- }
-
-- if (ht_nss_mask != vht_nss_mask)
-+ he_cap = ieee80211_get_he_iftype_cap_vif(sband, vif);
-+ if (!he_cap)
-+ return false;
-+
-+ he_mcs_map = le16_to_cpu(ath12k_mac_get_tx_mcs_map(he_cap));
-+
-+ for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++) {
-+ if (mask->control[band].he_mcs[i] == 0)
-+ continue;
-+
-+ if (mask->control[band].he_mcs[i] ==
-+ ath12k_mac_get_max_he_mcs_map(he_mcs_map, i))
-+ he_nss_mask |= BIT(i);
-+ else
-+ return false;
-+ }
-+
-+ if (ht_nss_mask != vht_nss_mask || ht_nss_mask != he_nss_mask)
- return false;
-
- if (ht_nss_mask == 0)
-@@ -11122,54 +11423,182 @@ ath12k_mac_get_single_legacy_rate(struct
- return 0;
- }
-
--static int ath12k_mac_set_fixed_rate_params(struct ath12k_link_vif *arvif,
-- u32 rate, u8 nss, u8 sgi, u8 ldpc)
-+static int
-+ath12k_mac_set_fixed_rate_gi_ltf(struct ath12k_link_vif *arvif, u8 he_gi, u8 he_ltf)
- {
- struct ath12k *ar = arvif->ar;
-- u32 vdev_param;
- int ret;
-
- lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
-
-- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac set fixed rate params vdev %i rate 0x%02x nss %u sgi %u\n",
-- arvif->vdev_id, rate, nss, sgi);
-+ /* 0.8 = 0, 1.6 = 2 and 3.2 = 3. */
-+ if (he_gi && he_gi != 0xFF)
-+ he_gi += 1;
-
-- vdev_param = WMI_VDEV_PARAM_FIXED_RATE;
- ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
-- vdev_param, rate);
-+ WMI_VDEV_PARAM_SGI, he_gi);
- if (ret) {
-- ath12k_warn(ar->ab, "failed to set fixed rate param 0x%02x: %d\n",
-- rate, ret);
-+ ath12k_warn(ar->ab, "failed to set HE GI:%d, error:%d\n",
-+ he_gi, ret);
- return ret;
- }
-+ /* start from 1 */
-+ if (he_ltf != 0xFF)
-+ he_ltf += 1;
-
-- vdev_param = WMI_VDEV_PARAM_NSS;
- ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
-- vdev_param, nss);
-+ WMI_VDEV_PARAM_HE_LTF, he_ltf);
- if (ret) {
-- ath12k_warn(ar->ab, "failed to set nss param %d: %d\n",
-- nss, ret);
-+ ath12k_warn(ar->ab, "failed to set HE LTF:%d, error:%d\n",
-+ he_ltf, ret);
- return ret;
- }
-+ return 0;
-+}
-+
-+static int
-+ath12k_mac_set_auto_rate_gi_ltf(struct ath12k_link_vif *arvif, u16 he_gi, u8 he_ltf)
-+{
-+ struct ath12k *ar = arvif->ar;
-+ int ret;
-+ u32 he_ar_gi_ltf;
-+
-+ if (he_gi != 0xFF) {
-+ switch (he_gi) {
-+ case NL80211_RATE_INFO_HE_GI_0_8:
-+ he_gi = WMI_AUTORATE_800NS_GI;
-+ break;
-+ case NL80211_RATE_INFO_HE_GI_1_6:
-+ he_gi = WMI_AUTORATE_1600NS_GI;
-+ break;
-+ case NL80211_RATE_INFO_HE_GI_3_2:
-+ he_gi = WMI_AUTORATE_3200NS_GI;
-+ break;
-+ default:
-+ ath12k_warn(ar->ab, "Invalid GI\n");
-+ return -EINVAL;
-+ }
-+ }
-+
-+ if (he_ltf != 0xFF) {
-+ switch (he_ltf) {
-+ case NL80211_RATE_INFO_HE_1XLTF:
-+ he_ltf = WMI_HE_AUTORATE_LTF_1X;
-+ break;
-+ case NL80211_RATE_INFO_HE_2XLTF:
-+ he_ltf = WMI_HE_AUTORATE_LTF_2X;
-+ break;
-+ case NL80211_RATE_INFO_HE_4XLTF:
-+ he_ltf = WMI_HE_AUTORATE_LTF_4X;
-+ break;
-+ default:
-+ ath12k_warn(ar->ab, "Invalid LTF\n");
-+ return -EINVAL;
-+ }
-+ }
-+
-+ he_ar_gi_ltf = he_gi | he_ltf;
-
-- vdev_param = WMI_VDEV_PARAM_SGI;
- ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
-- vdev_param, sgi);
-+ WMI_VDEV_PARAM_AUTORATE_MISC_CFG,
-+ he_ar_gi_ltf);
- if (ret) {
-- ath12k_warn(ar->ab, "failed to set sgi param %d: %d\n",
-- sgi, ret);
-+ ath12k_warn(ar->ab,
-+ "failed to set HE autorate GI:%u, LTF:%u params, error:%d\n",
-+ he_gi, he_ltf, ret);
- return ret;
- }
-
-- vdev_param = WMI_VDEV_PARAM_LDPC;
-+ return 0;
-+}
-+
-+static u32 ath12k_mac_nlgi_to_wmigi(enum nl80211_txrate_gi gi)
-+{
-+ switch (gi) {
-+ case NL80211_TXRATE_DEFAULT_GI:
-+ return WMI_GI_400_NS;
-+ case NL80211_TXRATE_FORCE_LGI:
-+ return WMI_GI_800_NS;
-+ default:
-+ return WMI_GI_400_NS;
-+ }
-+}
-+
-+static int ath12k_mac_set_rate_params(struct ath12k_link_vif *arvif,
-+ u32 rate, u8 nss, u8 sgi, u8 ldpc,
-+ u8 he_gi, u8 he_ltf, bool he_fixed_rate)
-+{
-+ struct ieee80211_bss_conf *link_conf;
-+ struct ath12k *ar = arvif->ar;
-+ u32 vdev_param;
-+ u32 param_value;
-+ int ret;
-+ bool he_support;
-+
-+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
-+
-+ link_conf = ath12k_mac_get_link_bss_conf(arvif);
-+ if (!link_conf)
-+ return -EINVAL;
-+
-+ he_support = link_conf->he_support;
-+
-+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
-+ "mac set rate params vdev %i rate 0x%02x nss 0x%02x sgi 0x%02x ldpc 0x%02x\n",
-+ arvif->vdev_id, rate, nss, sgi, ldpc);
-+
-+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
-+ "he_gi 0x%02x he_ltf 0x%02x he_fixed_rate %d\n", he_gi,
-+ he_ltf, he_fixed_rate);
-+
-+ if (!he_support) {
-+ vdev_param = WMI_VDEV_PARAM_FIXED_RATE;
-+ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
-+ vdev_param, rate);
-+ if (ret) {
-+ ath12k_warn(ar->ab, "failed to set fixed rate param 0x%02x: %d\n",
-+ rate, ret);
-+ return ret;
-+ }
-+ }
-+
-+ vdev_param = WMI_VDEV_PARAM_NSS;
-+
- ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
-- vdev_param, ldpc);
-+ vdev_param, nss);
-+ if (ret) {
-+ ath12k_warn(ar->ab, "failed to set nss param %d: %d\n",
-+ nss, ret);
-+ return ret;
-+ }
-+
-+ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
-+ WMI_VDEV_PARAM_LDPC, ldpc);
- if (ret) {
- ath12k_warn(ar->ab, "failed to set ldpc param %d: %d\n",
- ldpc, ret);
- return ret;
- }
-
-+ if (he_support) {
-+ if (he_fixed_rate)
-+ ret = ath12k_mac_set_fixed_rate_gi_ltf(arvif, he_gi, he_ltf);
-+ else
-+ ret = ath12k_mac_set_auto_rate_gi_ltf(arvif, he_gi, he_ltf);
-+ if (ret)
-+ return ret;
-+ } else {
-+ vdev_param = WMI_VDEV_PARAM_SGI;
-+ param_value = ath12k_mac_nlgi_to_wmigi(sgi);
-+ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
-+ vdev_param, param_value);
-+ if (ret) {
-+ ath12k_warn(ar->ab, "failed to set sgi param %d: %d\n",
-+ sgi, ret);
-+ return ret;
-+ }
-+ }
-+
- return 0;
- }
-
-@@ -11198,6 +11627,31 @@ ath12k_mac_vht_mcs_range_present(struct
- return true;
- }
-
-+static bool
-+ath12k_mac_he_mcs_range_present(struct ath12k *ar,
-+ enum nl80211_band band,
-+ const struct cfg80211_bitrate_mask *mask)
-+{
-+ int i;
-+ u16 he_mcs;
-+
-+ for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
-+ he_mcs = mask->control[band].he_mcs[i];
-+
-+ switch (he_mcs) {
-+ case 0:
-+ case BIT(8) - 1:
-+ case BIT(10) - 1:
-+ case BIT(12) - 1:
-+ break;
-+ default:
-+ return false;
-+ }
-+ }
-+
-+ return true;
-+}
-+
- static void ath12k_mac_set_bitrate_mask_iter(void *data,
- struct ieee80211_sta *sta)
- {
-@@ -11206,7 +11660,10 @@ static void ath12k_mac_set_bitrate_mask_
- struct ath12k_link_sta *arsta;
- struct ath12k *ar = arvif->ar;
-
-- arsta = rcu_dereference(ahsta->link[arvif->link_id]);
-+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
-+
-+ arsta = wiphy_dereference(ath12k_ar_to_hw(ar)->wiphy,
-+ ahsta->link[arvif->link_id]);
- if (!arsta || arsta->arvif != arvif)
- return;
-
-@@ -11244,6 +11701,61 @@ static void ath12k_mac_disable_peer_fixe
- arsta->addr, ret);
- }
-
-+static bool
-+ath12k_mac_validate_fixed_rate_settings(struct ath12k *ar, enum nl80211_band band,
-+ const struct cfg80211_bitrate_mask *mask,
-+ unsigned int link_id)
-+{
-+ bool he_fixed_rate = false, vht_fixed_rate = false;
-+ const u16 *vht_mcs_mask, *he_mcs_mask;
-+ struct ieee80211_link_sta *link_sta;
-+ struct ath12k_peer *peer, *tmp;
-+ u8 vht_nss, he_nss;
-+ int ret = true;
-+
-+ vht_mcs_mask = mask->control[band].vht_mcs;
-+ he_mcs_mask = mask->control[band].he_mcs;
-+
-+ if (ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask) == 1)
-+ vht_fixed_rate = true;
-+
-+ if (ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask) == 1)
-+ he_fixed_rate = true;
-+
-+ if (!vht_fixed_rate && !he_fixed_rate)
-+ return true;
-+
-+ vht_nss = ath12k_mac_max_vht_nss(vht_mcs_mask);
-+ he_nss = ath12k_mac_max_he_nss(he_mcs_mask);
-+
-+ rcu_read_lock();
-+ spin_lock_bh(&ar->ab->base_lock);
-+ list_for_each_entry_safe(peer, tmp, &ar->ab->peers, list) {
-+ if (peer->sta) {
-+ link_sta = rcu_dereference(peer->sta->link[link_id]);
-+ if (!link_sta) {
-+ ret = false;
-+ goto exit;
-+ }
-+
-+ if (vht_fixed_rate && (!link_sta->vht_cap.vht_supported ||
-+ link_sta->rx_nss < vht_nss)) {
-+ ret = false;
-+ goto exit;
-+ }
-+ if (he_fixed_rate && (!link_sta->he_cap.has_he ||
-+ link_sta->rx_nss < he_nss)) {
-+ ret = false;
-+ goto exit;
-+ }
-+ }
-+ }
-+exit:
-+ spin_unlock_bh(&ar->ab->base_lock);
-+ rcu_read_unlock();
-+ return ret;
-+}
-+
- static int
- ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
-@@ -11256,13 +11768,17 @@ ath12k_mac_op_set_bitrate_mask(struct ie
- enum nl80211_band band;
- const u8 *ht_mcs_mask;
- const u16 *vht_mcs_mask;
-+ const u16 *he_mcs_mask;
-+ u8 he_ltf = 0;
-+ u8 he_gi = 0;
- u32 rate;
-- u8 nss;
-+ u8 nss, mac_nss;
- u8 sgi;
- u8 ldpc;
- int single_nss;
- int ret;
- int num_rates;
-+ bool he_fixed_rate = false;
-
- lockdep_assert_wiphy(hw->wiphy);
-
-@@ -11277,14 +11793,18 @@ ath12k_mac_op_set_bitrate_mask(struct ie
- band = def.chan->band;
- ht_mcs_mask = mask->control[band].ht_mcs;
- vht_mcs_mask = mask->control[band].vht_mcs;
-+ he_mcs_mask = mask->control[band].he_mcs;
- ldpc = !!(ar->ht_cap_info & WMI_HT_CAP_LDPC);
-
- sgi = mask->control[band].gi;
-- if (sgi == NL80211_TXRATE_FORCE_LGI) {
-+ if (sgi == NL80211_TXRATE_FORCE_SGI) {
- ret = -EINVAL;
- goto out;
- }
-
-+ he_gi = mask->control[band].he_gi;
-+ he_ltf = mask->control[band].he_ltf;
-+
- /* mac80211 doesn't support sending a fixed HT/VHT MCS alone, rather it
- * requires passing at least one of used basic rates along with them.
- * Fixed rate setting across different preambles(legacy, HT, VHT) is
-@@ -11301,18 +11821,31 @@ ath12k_mac_op_set_bitrate_mask(struct ie
- arvif->vdev_id, ret);
- goto out;
- }
-+
- ieee80211_iterate_stations_mtx(hw,
- ath12k_mac_disable_peer_fixed_rate,
- arvif);
-- } else if (ath12k_mac_bitrate_mask_get_single_nss(ar, band, mask,
-+ } else if (ath12k_mac_bitrate_mask_get_single_nss(ar, vif, band, mask,
- &single_nss)) {
- rate = WMI_FIXED_RATE_NONE;
- nss = single_nss;
-+ arvif->bitrate_mask = *mask;
-+
-+ ieee80211_iterate_stations_atomic(hw,
-+ ath12k_mac_set_bitrate_mask_iter,
-+ arvif);
- } else {
- rate = WMI_FIXED_RATE_NONE;
-- nss = min_t(u32, ar->num_tx_chains,
-- max(ath12k_mac_max_ht_nss(ht_mcs_mask),
-- ath12k_mac_max_vht_nss(vht_mcs_mask)));
-+
-+ if (!ath12k_mac_validate_fixed_rate_settings(ar, band,
-+ mask, arvif->link_id))
-+ ath12k_warn(ar->ab,
-+ "failed to update fixed rate settings due to mcs/nss incompatibility\n");
-+
-+ mac_nss = max3(ath12k_mac_max_ht_nss(ht_mcs_mask),
-+ ath12k_mac_max_vht_nss(vht_mcs_mask),
-+ ath12k_mac_max_he_nss(he_mcs_mask));
-+ nss = min_t(u32, ar->num_tx_chains, mac_nss);
-
- /* If multiple rates across different preambles are given
- * we can reconfigure this info with all peers using PEER_ASSOC
-@@ -11344,9 +11877,21 @@ ath12k_mac_op_set_bitrate_mask(struct ie
- */
- ath12k_warn(ar->ab,
- "Setting more than one MCS Value in bitrate mask not supported\n");
-- return -EINVAL;
-+ ret = -EINVAL;
-+ goto out;
- }
-
-+ num_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask);
-+ if (num_rates == 1)
-+ he_fixed_rate = true;
-+
-+ if (!ath12k_mac_he_mcs_range_present(ar, band, mask) &&
-+ num_rates > 1) {
-+ ath12k_warn(ar->ab,
-+ "Setting more than one HE MCS Value in bitrate mask not supported\n");
-+ ret = -EINVAL;
-+ goto out;
-+ }
- ieee80211_iterate_stations_mtx(hw,
- ath12k_mac_disable_peer_fixed_rate,
- arvif);
-@@ -11357,9 +11902,10 @@ ath12k_mac_op_set_bitrate_mask(struct ie
- arvif);
- }
-
-- ret = ath12k_mac_set_fixed_rate_params(arvif, rate, nss, sgi, ldpc);
-+ ret = ath12k_mac_set_rate_params(arvif, rate, nss, sgi, ldpc, he_gi,
-+ he_ltf, he_fixed_rate);
- if (ret) {
-- ath12k_warn(ar->ab, "failed to set fixed rate params on vdev %i: %d\n",
-+ ath12k_warn(ar->ab, "failed to set rate params on vdev %i: %d\n",
- arvif->vdev_id, ret);
- }
-
---- a/drivers/net/wireless/ath/ath12k/wmi.h
-+++ b/drivers/net/wireless/ath/ath12k/wmi.h
-@@ -222,6 +222,22 @@ enum WMI_HOST_WLAN_BAND {
- WMI_HOST_WLAN_2GHZ_5GHZ_CAP = 3,
- };
-
-+/* Parameters used for WMI_VDEV_PARAM_AUTORATE_MISC_CFG command.
-+ * Used only for HE auto rate mode.
-+ */
-+enum {
-+ /* HE LTF related configuration */
-+ WMI_HE_AUTORATE_LTF_1X = BIT(0),
-+ WMI_HE_AUTORATE_LTF_2X = BIT(1),
-+ WMI_HE_AUTORATE_LTF_4X = BIT(2),
-+
-+ /* HE GI related configuration */
-+ WMI_AUTORATE_400NS_GI = BIT(8),
-+ WMI_AUTORATE_800NS_GI = BIT(9),
-+ WMI_AUTORATE_1600NS_GI = BIT(10),
-+ WMI_AUTORATE_3200NS_GI = BIT(11),
-+};
-+
- enum wmi_cmd_group {
- /* 0 to 2 are reserved */
- WMI_GRP_START = 0x3,
-@@ -1169,7 +1185,9 @@ enum wmi_tlv_vdev_param {
- WMI_VDEV_PARAM_HE_RANGE_EXT,
- WMI_VDEV_PARAM_ENABLE_BCAST_PROBE_RESPONSE,
- WMI_VDEV_PARAM_FILS_MAX_CHANNEL_GUARD_TIME,
-+ WMI_VDEV_PARAM_HE_LTF = 0x74,
- WMI_VDEV_PARAM_BA_MODE = 0x7e,
-+ WMI_VDEV_PARAM_AUTORATE_MISC_CFG = 0x80,
- WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE = 0x87,
- WMI_VDEV_PARAM_6GHZ_PARAMS = 0x99,
- WMI_VDEV_PARAM_PROTOTYPE = 0x8000,
-@@ -3631,6 +3649,15 @@ struct wmi_force_fw_hang_cmd {
- __le32 delay_time_ms;
- } __packed;
-
-+/* Param values to be sent for WMI_VDEV_PARAM_SGI param_id
-+ * which are used in 11n, 11ac systems
-+ * @WMI_GI_800_NS - Always uses 0.8us (Long GI)
-+ * @WMI_GI_400_NS - Firmware switches between 0.4us (Short GI)
-+ * and 0.8us (Long GI) based on packet error rate.
-+ */
-+#define WMI_GI_800_NS 0
-+#define WMI_GI_400_NS 1
-+
- struct wmi_vdev_set_param_cmd {
- __le32 tlv_header;
- __le32 vdev_id;
+++ /dev/null
-From patchwork Wed May 21 22:45:37 2025
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Id: 14096121
-Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com
- [205.220.180.131])
- (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
- (No client certificate requested)
- by smtp.subspace.kernel.org (Postfix) with ESMTPS id ED55023958A
-Authentication-Results: smtp.subspace.kernel.org;
- arc=none smtp.client-ip=205.220.180.131
-ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
- t=1747867560; cv=none;
- b=R6R1l/0hUMYWkLzVM4w8Z2s3aU01ujlrdBV4IEYLrqQ3CzuP8xd2fnZMcdbVAFvXd/hepJKOZrFod6RG43u2TuGCQ5wM3SKIqyk0c/MlskZk+jnUnvm9WtrezJS82phw1G2mJ8NiYsKzmcJGMQtaYfl3jWA4o+BGMGyOg0Keb/M=
-ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
- s=arc-20240116; t=1747867560; c=relaxed/simple;
- bh=HUqzq2V1sSbcLZxqxveNb5xXvMg5sfyIhSzn4mKsdms=;
- h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:
- MIME-Version:Content-Type;
- b=G9poRT2jwhhAC0htiaG4SIE8b1DuTf63uDCDCGj5WoQ4B/v/NWtaqtzBWJF4c7UuQBso4JO4X9auJyfxJ4SxUBrULdlJq7mvAs7nxFOPEBDBltLKWCZznLwuuuo690MjvUQ5mfKt/Oy+uREyur4vXsQtfSBZc0DSZUlC5R+Z2Mc=
-ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
- dmarc=pass (p=none dis=none) header.from=quicinc.com;
- spf=pass smtp.mailfrom=quicinc.com;
- header.b=cu63IdMd; arc=none smtp.client-ip=205.220.180.131
-Authentication-Results: smtp.subspace.kernel.org;
- dmarc=pass (p=none dis=none) header.from=quicinc.com
-Authentication-Results: smtp.subspace.kernel.org;
- spf=pass smtp.mailfrom=quicinc.com
-Authentication-Results: smtp.subspace.kernel.org;
- header.b="cu63IdMd"
-Received: from pps.filterd (m0279871.ppops.net [127.0.0.1])
- by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id
- 54LJgw7Z025025;
- Wed, 21 May 2025 22:45:56 GMT
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=
- cc:content-transfer-encoding:content-type:date:from:in-reply-to
- :message-id:mime-version:references:subject:to; s=qcppdkim1; bh=
- 90lF32RvbNU2yyxl2mGBEewKfDvRJ7MRRLe6DgCwXFs=; b=cu63IdMdS+nJIsqy
- ktY/ZQ/qTTWf2MpubSMC9UftiwnI9Xj6K8LFE0q+NvCN2EgZKzf+OzyW9wbbRepN
- Q3ZYBAR3lFyw40J6AZgpAuPiq7Y+eqt7l8jc+/2bb2+imOzvWHwFkXSvc8nijnHX
- ZLEU29M0xloyHeJ7xLbumzRdfcCJ6357/HKp9U3mLvEfpLY97t5/H3yEJWHQmnvE
- aHkFaLM6Ru2R2+nzPDylKcY+TZsqv306oEqydWI33ANyvfDkWJqbQjtQ+geTkJxC
- syi9ZifD5zPdOjb9YWNn0V8mWUBRx6hW8ZKU/L3gWGXjkvyRHneZ4AOz83Tp9Ym4
- L34jSQ==
-Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com
- [129.46.96.20])
- by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwf6vbsf-1
- (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
- Wed, 21 May 2025 22:45:55 +0000 (GMT)
-Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com
- [10.47.209.196])
- by NALASPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id
- 54LMjsWN022226
- (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
- Wed, 21 May 2025 22:45:54 GMT
-Received: from ath12k-linux2.qualcomm.com (10.80.80.8) by
- nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server
- (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
- 15.2.1544.9; Wed, 21 May 2025 15:45:54 -0700
- Pradeep Kumar Chitrapu
-Subject: [PATCH ath-next V14 7/9] wifi: ath12k: clean up 80P80 support
-Date: Wed, 21 May 2025 15:45:37 -0700
-X-Mailer: git-send-email 2.43.0
-Precedence: bulk
-List-Id: <linux-wireless.vger.kernel.org>
-MIME-Version: 1.0
-X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To
- nalasex01a.na.qualcomm.com (10.47.209.196)
-X-QCInternal: smtphost
-X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800
- signatures=585085
-X-Proofpoint-GUID: xDBdjIlSrmWJZkBfMwcImhxnyTIR4551
-X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIxMDIyNiBTYWx0ZWRfX75XKL//oF16a
- YMA/60ZSduIYMzTQ+PpEhRfS8BSEJ3JAYNLLDjp3b1hmrHJmdqMnxgbya6RQ+qeAISgkr8ZWIMx
- fGx/btrlFP2SbXd0JWwSMOApD3LJewBu/ZeBWBDEWbbO00LOGnR0aFqmCeym6YSeYyakVcNd8nQ
- 0JnPxxBLeXeYPpIZTFMD6TpVFyfvtCG9jpMOI27FLBdHLednVW2yrOx5b62xwy181re5iN4XOki
- 1M/HJRMACpfQJImHpO9X3rRh2j79oKIKVwa3UjV8A7vD3noV/pV0SOTZP0awMYQH/Pn91nji685
- auXzHG2pai3Byw89+jYZIG2xfiqBcBwIEARvw52XSv3glk0tSvLDxNo8nyFNPsZ63g70USl1IlC
- AKhW+QOw9/zkn3oCB+3fZZ/y+F4vlu4OzN4gETU+6p3798YiFGWMvocQnI/Ig7Unex9rmOP5
-X-Authority-Analysis: v=2.4 cv=fZOty1QF c=1 sm=1 tr=0 ts=682e57a3 cx=c_pps
- a=ouPCqIW2jiPt+lZRy3xVPw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17
- a=GEpy-HfZoHoA:10 a=dt9VzEwgFbYA:10 a=COk6AnOGAAAA:8 a=QHHbJxpVzSBZVvfXPLwA:9
- a=TjNXssC_j7lpFel5tvFf:22
-X-Proofpoint-ORIG-GUID: xDBdjIlSrmWJZkBfMwcImhxnyTIR4551
-X-Proofpoint-Virus-Version: vendor=baseguard
- engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40
- definitions=2025-05-21_07,2025-05-20_03,2025-03-28_01
-X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0
- clxscore=1015 mlxscore=0 adultscore=0 spamscore=0 bulkscore=0 suspectscore=0
- malwarescore=0 priorityscore=1501 impostorscore=0 mlxlogscore=999
- lowpriorityscore=0 phishscore=0 classifier=spam authscore=0 authtc=n/a
- authcc= route=outbound adjust=0 reason=mlx scancount=1
- engine=8.19.0-2505160000 definitions=main-2505210226
-
-Clean up unused 80P80 references as hardware does not support
-it. This is applicable to both QCN9274 and WCN7850.
-
-Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
-
----
- drivers/net/wireless/ath/ath12k/mac.c | 48 ++++++---------------------
- drivers/net/wireless/ath/ath12k/wmi.c | 2 --
- drivers/net/wireless/ath/ath12k/wmi.h | 1 -
- 3 files changed, 10 insertions(+), 41 deletions(-)
-
---- a/drivers/net/wireless/ath/ath12k/mac.c
-+++ b/drivers/net/wireless/ath/ath12k/mac.c
-@@ -209,7 +209,7 @@ ath12k_phymodes[NUM_NL80211_BANDS][ATH12
- [NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40,
- [NL80211_CHAN_WIDTH_80] = MODE_11BE_EHT80,
- [NL80211_CHAN_WIDTH_160] = MODE_11BE_EHT160,
-- [NL80211_CHAN_WIDTH_80P80] = MODE_11BE_EHT80_80,
-+ [NL80211_CHAN_WIDTH_80P80] = MODE_UNKNOWN,
- [NL80211_CHAN_WIDTH_320] = MODE_11BE_EHT320,
- },
- [NL80211_BAND_6GHZ] = {
-@@ -220,7 +220,7 @@ ath12k_phymodes[NUM_NL80211_BANDS][ATH12
- [NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40,
- [NL80211_CHAN_WIDTH_80] = MODE_11BE_EHT80,
- [NL80211_CHAN_WIDTH_160] = MODE_11BE_EHT160,
-- [NL80211_CHAN_WIDTH_80P80] = MODE_11BE_EHT80_80,
-+ [NL80211_CHAN_WIDTH_80P80] = MODE_UNKNOWN,
- [NL80211_CHAN_WIDTH_320] = MODE_11BE_EHT320,
- },
-
-@@ -2556,17 +2556,6 @@ static void ath12k_peer_assoc_h_he(struc
-
- switch (link_sta->bandwidth) {
- case IEEE80211_STA_RX_BW_160:
-- if (he_cap->he_cap_elem.phy_cap_info[0] &
-- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) {
-- v = ath12k_peer_assoc_h_he_limit(v, he_mcs_mask);
-- arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
--
-- v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80p80);
-- arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
--
-- arg->peer_he_mcs_count++;
-- he_tx_mcs = v;
-- }
- v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
- arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
-
-@@ -2853,16 +2842,11 @@ static enum wmi_phy_mode ath12k_mac_get_
- struct ieee80211_link_sta *link_sta)
- {
- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) {
-- switch (link_sta->vht_cap.cap &
-- IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
-- case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
-+ if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)
- return MODE_11AC_VHT160;
-- case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
-- return MODE_11AC_VHT80_80;
-- default:
-- /* not sure if this is a valid case? */
-- return MODE_11AC_VHT160;
-- }
-+
-+ /* not sure if this is a valid case? */
-+ return MODE_11AC_VHT160;
- }
-
- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80)
-@@ -2884,11 +2868,8 @@ static enum wmi_phy_mode ath12k_mac_get_
- if (link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
- return MODE_11AX_HE160;
-- else if (link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
-- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
-- return MODE_11AX_HE80_80;
-- /* not sure if this is a valid case? */
-- return MODE_11AX_HE160;
-+
-+ return MODE_UNKNOWN;
- }
-
- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80)
-@@ -2916,14 +2897,10 @@ static enum wmi_phy_mode ath12k_mac_get_
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
- return MODE_11BE_EHT160;
-
-- if (link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
-- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
-- return MODE_11BE_EHT80_80;
--
- ath12k_warn(ar->ab, "invalid EHT PHY capability info for 160 Mhz: %d\n",
- link_sta->he_cap.he_cap_elem.phy_cap_info[0]);
-
-- return MODE_11BE_EHT160;
-+ return MODE_UNKNOWN;
- }
-
- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80)
-@@ -7630,8 +7607,6 @@ static void ath12k_mac_set_hemcsmap(stru
- mcs_nss->tx_mcs_80 = cpu_to_le16(txmcs_map & 0xffff);
- mcs_nss->rx_mcs_160 = cpu_to_le16(rxmcs_map & 0xffff);
- mcs_nss->tx_mcs_160 = cpu_to_le16(txmcs_map & 0xffff);
-- mcs_nss->rx_mcs_80p80 = cpu_to_le16(rxmcs_map & 0xffff);
-- mcs_nss->tx_mcs_80p80 = cpu_to_le16(txmcs_map & 0xffff);
- }
-
- static void ath12k_mac_copy_he_cap(struct ath12k *ar,
-@@ -7653,6 +7628,7 @@ static void ath12k_mac_copy_he_cap(struc
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
-+ /* 80PLUS80 is not supported */
- he_cap_elem->phy_cap_info[0] &=
- ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G;
- he_cap_elem->phy_cap_info[5] &=
-@@ -11309,10 +11285,6 @@ static __le16
- ath12k_mac_get_tx_mcs_map(const struct ieee80211_sta_he_cap *he_cap)
- {
- if (he_cap->he_cap_elem.phy_cap_info[0] &
-- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
-- return he_cap->he_mcs_nss_supp.tx_mcs_80p80;
--
-- if (he_cap->he_cap_elem.phy_cap_info[0] &
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
- return he_cap->he_mcs_nss_supp.tx_mcs_160;
-
---- a/drivers/net/wireless/ath/ath12k/wmi.c
-+++ b/drivers/net/wireless/ath/ath12k/wmi.c
-@@ -1066,8 +1066,6 @@ static void ath12k_wmi_put_wmi_channel(s
- chan->band_center_freq1 = cpu_to_le32(center_freq1 - 40);
-
- chan->band_center_freq2 = cpu_to_le32(center_freq1);
-- } else if (arg->mode == MODE_11BE_EHT80_80) {
-- chan->band_center_freq2 = cpu_to_le32(arg->band_center_freq2);
- } else {
- chan->band_center_freq2 = 0;
- }
---- a/drivers/net/wireless/ath/ath12k/wmi.h
-+++ b/drivers/net/wireless/ath/ath12k/wmi.h
-@@ -3798,7 +3798,6 @@ struct wmi_vdev_install_key_arg {
- #define WMI_HOST_MAX_HE_RATE_SET 3
- #define WMI_HECAP_TXRX_MCS_NSS_IDX_80 0
- #define WMI_HECAP_TXRX_MCS_NSS_IDX_160 1
--#define WMI_HECAP_TXRX_MCS_NSS_IDX_80_80 2
-
- #define ATH12K_WMI_MLO_MAX_PARTNER_LINKS \
- (ATH12K_WMI_MLO_MAX_LINKS + ATH12K_MAX_NUM_BRIDGE_LINKS - 1)
+++ /dev/null
-From patchwork Wed May 21 22:45:38 2025
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Id: 14096124
-Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com
- [205.220.180.131])
- (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
- (No client certificate requested)
- by smtp.subspace.kernel.org (Postfix) with ESMTPS id DEE9223A9AA
-Authentication-Results: smtp.subspace.kernel.org;
- arc=none smtp.client-ip=205.220.180.131
-ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
- t=1747867561; cv=none;
- b=qWgm5H8L0Zhrc5crkCw7SBoGEQ8yf+aC0TSWOzfiTwcAddeStpjorEa3XaBl0GOhHPRaECOhMSNqu88tQ5CzCGmumBQ3QLC6mod6Tb0Y0PdeUJm3YoGKcI+F0oE3g5kCHaU9LRKKnmMZQS72kE7dO+lEBfwMIuCX/VwV066B1p8=
-ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
- s=arc-20240116; t=1747867561; c=relaxed/simple;
- bh=61S52HJJJauXcXkg3NpFqkwtGSPNO+bmTpNYu1v9AKM=;
- h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:
- MIME-Version:Content-Type;
- b=gi5WIxM8SYlljyfdAVTdIK6JQ5jJHPGGfdxPkwbtEaPElRA55vurxkaaJ0RktTtDYYJEn7KLZFieBHAv5/nEcrDjL4NGvgT3wiAoGcbsd+TIF6w5J2RSmAwhAP008N5swveLHDzJ0M9TrtQj2HHndc8JPD4oGWbcEqKQqHSq8ck=
-ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
- dmarc=pass (p=none dis=none) header.from=quicinc.com;
- spf=pass smtp.mailfrom=quicinc.com;
- header.b=lMYw009C; arc=none smtp.client-ip=205.220.180.131
-Authentication-Results: smtp.subspace.kernel.org;
- dmarc=pass (p=none dis=none) header.from=quicinc.com
-Authentication-Results: smtp.subspace.kernel.org;
- spf=pass smtp.mailfrom=quicinc.com
-Authentication-Results: smtp.subspace.kernel.org;
- header.b="lMYw009C"
-Received: from pps.filterd (m0279868.ppops.net [127.0.0.1])
- by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id
- 54LJgEPE029249;
- Wed, 21 May 2025 22:45:56 GMT
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=
- cc:content-transfer-encoding:content-type:date:from:in-reply-to
- :message-id:mime-version:references:subject:to; s=qcppdkim1; bh=
- ph+yJaIkwYsZzzEsymzTjupgmHjdwFMJhbEzuPrYvfY=; b=lMYw009CSvZqDxkz
- +HCEzcZhy6QO8G2ut93TJxHdCbVLlRaMNReXGlGqx2KRNracyLRkAQsC16i+QcpJ
- aHBvIE2c0/TEtBiyv3HzBf3/89R0POT080sz81P6go3m8w9bcIE+Q2DqjdhVNqu3
- AlV8qb6pj/QUVvDbJQxO1M9eCXSO6g2BBDjgRCktOu+x2TlxhdBZ/tJP+h0AUk+j
- YsH1LhcLOZYCFTJyB6IFmHWvtGk5Ef6i6D/tXyCL7nQiDP/R1v2PcdlLlI5e5/PO
- FhKB2+RCmSyJUtyaAHHi/mVen5yqFX2K3/vL3BtprRAJINhFxQrLs6xLIQabELzj
- KCstuQ==
-Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com
- [129.46.96.20])
- by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwfb4b3x-1
- (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
- Wed, 21 May 2025 22:45:55 +0000 (GMT)
-Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com
- [10.47.209.196])
- by NALASPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id
- 54LMjtX2022238
- (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
- Wed, 21 May 2025 22:45:55 GMT
-Received: from ath12k-linux2.qualcomm.com (10.80.80.8) by
- nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server
- (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
- 15.2.1544.9; Wed, 21 May 2025 15:45:54 -0700
- Pradeep Kumar Chitrapu
- "Jeff
-Subject: [PATCH ath-next V14 8/9] wifi: ath12k: add support for 160 MHz
- bandwidth
-Date: Wed, 21 May 2025 15:45:38 -0700
-X-Mailer: git-send-email 2.43.0
-Precedence: bulk
-List-Id: <linux-wireless.vger.kernel.org>
-MIME-Version: 1.0
-X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To
- nalasex01a.na.qualcomm.com (10.47.209.196)
-X-QCInternal: smtphost
-X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800
- signatures=585085
-X-Proofpoint-ORIG-GUID: T9MbsOp4F8M93FD6ZEyfm1BTh5tEiCIl
-X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIxMDIyNiBTYWx0ZWRfX0EeEFBAyVxZV
- WX6jh2dkCn4P+eViI8Gvz/6S+yZ+Avx9/8To2mbulh5j1kDm92bEDu7iQtI17ILPnOgbUXWAjjt
- Z2LvemtbMzJe0lY0EjJNWWunihdlsXPAdOnZFjV0rOtakq8Xx4y8K45/1cGY9dQOApxDFC9HiLZ
- +FK9apopZ2DyP6haLf5HQI+6DC3wwgbEQlE+89g69hXEM8UePlFlsf0fpfIVgiWG73gfzHkrRPM
- 8ByVGmKpFSXIBmvY+EZZOPuPsQHt/91pIisXw5Joxdbl6Qf2anjuC0X4LPrTgTxgXWhljS4JdXo
- djhNt09IBnNuagxN9aMx/frUhqQPNL54kp/cXbpgcLQX0XQg8SOvwyxJs+CALQUyymluDLHyH9w
- UQUznCXFrps86AX/Fpnhrl9hqR5NO0/6oR340zsS7mvryRucOqzT7vc3WPMJEhW68VMCAl5Z
-X-Proofpoint-GUID: T9MbsOp4F8M93FD6ZEyfm1BTh5tEiCIl
-X-Authority-Analysis: v=2.4 cv=dLCmmPZb c=1 sm=1 tr=0 ts=682e57a4 cx=c_pps
- a=ouPCqIW2jiPt+lZRy3xVPw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17
- a=GEpy-HfZoHoA:10 a=dt9VzEwgFbYA:10 a=COk6AnOGAAAA:8 a=dOJm2eNAaUnF9U8lSB4A:9
- a=TjNXssC_j7lpFel5tvFf:22
-X-Proofpoint-Virus-Version: vendor=baseguard
- engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40
- definitions=2025-05-21_07,2025-05-20_03,2025-03-28_01
-X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0
- mlxscore=0 clxscore=1015 adultscore=0 bulkscore=0 phishscore=0 suspectscore=0
- impostorscore=0 malwarescore=0 lowpriorityscore=0 mlxlogscore=999 spamscore=0
- priorityscore=1501 classifier=spam authscore=0 authtc=n/a authcc=
- route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2505160000
- definitions=main-2505210226
-
-Add support to configure maximum NSS in 160 MHz bandwidth.
-Firmware advertises support for handling NSS ratio information
-as a part of service ready ext event using nss_ratio_enabled
-flag. Save this information in ath12k_pdev_cap to calculate
-NSS ratio.
-
-Additionally, reorder the code by moving
-ath12k_peer_assoc_h_phymode() before ath12k_peer_assoc_h_vht()
-to ensure that arg->peer_phymode correctly reflects the bandwidth
-in the max NSS calculation.
-
-Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
-
----
- drivers/net/wireless/ath/ath12k/core.h | 2 +
- drivers/net/wireless/ath/ath12k/mac.c | 89 ++++++++++++++++++++++----
- drivers/net/wireless/ath/ath12k/mac.h | 2 +
- drivers/net/wireless/ath/ath12k/wmi.c | 7 +-
- drivers/net/wireless/ath/ath12k/wmi.h | 28 ++++++++
- 5 files changed, 115 insertions(+), 13 deletions(-)
-
---- a/drivers/net/wireless/ath/ath12k/core.h
-+++ b/drivers/net/wireless/ath/ath12k/core.h
-@@ -879,6 +879,8 @@ struct ath12k_pdev_cap {
- struct ath12k_band_cap band[NUM_NL80211_BANDS];
- u32 eml_cap;
- u32 mld_cap;
-+ bool nss_ratio_enabled;
-+ u8 nss_ratio_info;
- };
-
- struct mlo_timestamp {
---- a/drivers/net/wireless/ath/ath12k/mac.c
-+++ b/drivers/net/wireless/ath/ath12k/mac.c
-@@ -2185,6 +2185,34 @@ ath12k_peer_assoc_h_vht_limit(u16 tx_mcs
- return tx_mcs_set;
- }
-
-+static u8 ath12k_get_nss_160mhz(struct ath12k *ar,
-+ u8 max_nss)
-+{
-+ u8 nss_ratio_info = ar->pdev->cap.nss_ratio_info;
-+ u8 max_sup_nss = 0;
-+
-+ switch (nss_ratio_info) {
-+ case WMI_NSS_RATIO_1BY2_NSS:
-+ max_sup_nss = max_nss >> 1;
-+ break;
-+ case WMI_NSS_RATIO_3BY4_NSS:
-+ ath12k_warn(ar->ab, "WMI_NSS_RATIO_3BY4_NSS not supported\n");
-+ break;
-+ case WMI_NSS_RATIO_1_NSS:
-+ max_sup_nss = max_nss;
-+ break;
-+ case WMI_NSS_RATIO_2_NSS:
-+ ath12k_warn(ar->ab, "WMI_NSS_RATIO_2_NSS not supported\n");
-+ break;
-+ default:
-+ ath12k_warn(ar->ab, "invalid nss ratio received from fw: %d\n",
-+ nss_ratio_info);
-+ break;
-+ }
-+
-+ return max_sup_nss;
-+}
-+
- static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
- struct ath12k_link_vif *arvif,
- struct ath12k_link_sta *arsta,
-@@ -2202,6 +2230,7 @@ static void ath12k_peer_assoc_h_vht(stru
- u8 max_nss, vht_mcs;
- int i, vht_nss, nss_idx;
- bool user_rate_valid = true;
-+ u32 rx_nss, tx_nss, nss_160;
-
- lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
-
-@@ -2306,10 +2335,24 @@ static void ath12k_peer_assoc_h_vht(stru
- /* TODO: Check */
- arg->tx_max_mcs_nss = 0xFF;
-
-- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x\n",
-- arsta->addr, arg->peer_max_mpdu, arg->peer_flags);
-+ if (arg->peer_phymode == MODE_11AC_VHT160) {
-+ tx_nss = ath12k_get_nss_160mhz(ar, max_nss);
-+ rx_nss = min(arg->peer_nss, tx_nss);
-+ arg->peer_bw_rxnss_override = ATH12K_BW_NSS_MAP_ENABLE;
-+
-+ if (!rx_nss) {
-+ ath12k_warn(ar->ab, "invalid max_nss\n");
-+ return;
-+ }
-+
-+ nss_160 = u32_encode_bits(rx_nss - 1, ATH12K_PEER_RX_NSS_160MHZ);
-+ arg->peer_bw_rxnss_override |= nss_160;
-+ }
-
-- /* TODO: rxnss_override */
-+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
-+ "mac vht peer %pM max_mpdu %d flags 0x%x nss_override 0x%x\n",
-+ arsta->addr, arg->peer_max_mpdu, arg->peer_flags,
-+ arg->peer_bw_rxnss_override);
- }
-
- static int ath12k_mac_get_max_he_mcs_map(u16 mcs_map, int nss)
-@@ -2402,6 +2445,7 @@ static void ath12k_peer_assoc_h_he(struc
- u16 he_tx_mcs = 0, v = 0;
- int he_nss, nss_idx;
- bool user_rate_valid = true;
-+ u32 rx_nss, tx_nss, nss_160;
-
- if (WARN_ON(ath12k_mac_vif_link_chan(vif, link_id, &def)))
- return;
-@@ -2599,9 +2643,25 @@ static void ath12k_peer_assoc_h_he(struc
- max_nss = min(max_nss, ar->num_tx_chains);
- arg->peer_nss = min(link_sta->rx_nss, max_nss);
-
-+ if (arg->peer_phymode == MODE_11AX_HE160) {
-+ tx_nss = ath12k_get_nss_160mhz(ar, max_nss);
-+ rx_nss = min(arg->peer_nss, tx_nss);
-+ arg->peer_bw_rxnss_override = ATH12K_BW_NSS_MAP_ENABLE;
-+
-+ if (!rx_nss) {
-+ ath12k_warn(ar->ab, "invalid max_nss\n");
-+ return;
-+ }
-+
-+ nss_160 = u32_encode_bits(rx_nss - 1, ATH12K_PEER_RX_NSS_160MHZ);
-+ arg->peer_bw_rxnss_override |= nss_160;
-+ }
-+
- ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
-- "mac he peer %pM nss %d mcs cnt %d\n",
-- arsta->addr, arg->peer_nss, arg->peer_he_mcs_count);
-+ "mac he peer %pM nss %d mcs cnt %d nss_override 0x%x\n",
-+ arsta->addr, arg->peer_nss,
-+ arg->peer_he_mcs_count,
-+ arg->peer_bw_rxnss_override);
- }
-
- static void ath12k_peer_assoc_h_he_6ghz(struct ath12k *ar,
-@@ -2842,10 +2902,13 @@ static enum wmi_phy_mode ath12k_mac_get_
- struct ieee80211_link_sta *link_sta)
- {
- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) {
-- if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)
-+ if (link_sta->vht_cap.cap & (IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
-+ IEEE80211_VHT_CAP_EXT_NSS_BW_MASK))
- return MODE_11AC_VHT160;
-
-- /* not sure if this is a valid case? */
-+ /* Allow STA to connect even if it does not explicitly advertise 160 MHz
-+ * support
-+ */
- return MODE_11AC_VHT160;
- }
-
-@@ -7379,10 +7442,8 @@ ath12k_create_vht_cap(struct ath12k *ar,
-
- ath12k_set_vht_txbf_cap(ar, &vht_cap.cap);
-
-- /* TODO: Enable back VHT160 mode once association issues are fixed */
-- /* Disabling VHT160 and VHT80+80 modes */
-- vht_cap.cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
-- vht_cap.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_160;
-+ /* 80P80 is not supported */
-+ vht_cap.cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
-
- rxmcs_map = 0;
- txmcs_map = 0;
-@@ -12654,7 +12715,8 @@ ath12k_mac_setup_radio_iface_comb(struct
- comb[0].radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
- BIT(NL80211_CHAN_WIDTH_20) |
- BIT(NL80211_CHAN_WIDTH_40) |
-- BIT(NL80211_CHAN_WIDTH_80);
-+ BIT(NL80211_CHAN_WIDTH_80) |
-+ BIT(NL80211_CHAN_WIDTH_160);
- }
-
- return 0;
-@@ -13031,6 +13093,9 @@ static int ath12k_mac_hw_register(struct
- ieee80211_hw_set(hw, REPORTS_LOW_ACK);
- ieee80211_hw_set(hw, NO_VIRTUAL_MONITOR);
-
-+ if (cap->nss_ratio_enabled)
-+ ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
-+
- if ((ht_cap & WMI_HT_CAP_ENABLED) || is_6ghz) {
- ieee80211_hw_set(hw, AMPDU_AGGREGATION);
- ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW);
---- a/drivers/net/wireless/ath/ath12k/mac.h
-+++ b/drivers/net/wireless/ath/ath12k/mac.h
-@@ -41,6 +41,8 @@ struct ath12k_generic_iter {
- #define IEEE80211_DISABLE_VHT_MCS_SUPPORT_0_11 BIT(24)
-
- #define ATH12K_CHAN_WIDTH_NUM 14
-+#define ATH12K_BW_NSS_MAP_ENABLE BIT(31)
-+#define ATH12K_PEER_RX_NSS_160MHZ GENMASK(2, 0)
-
- #define ATH12K_TX_POWER_MAX_VAL 70
- #define ATH12K_TX_POWER_MIN_VAL 0
---- a/drivers/net/wireless/ath/ath12k/wmi.c
-+++ b/drivers/net/wireless/ath/ath12k/wmi.c
-@@ -537,6 +537,10 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(st
- pdev_cap->he_mcs = le32_to_cpu(mac_caps->he_supp_mcs_5g);
- pdev_cap->tx_chain_mask = le32_to_cpu(mac_caps->tx_chain_mask_5g);
- pdev_cap->rx_chain_mask = le32_to_cpu(mac_caps->rx_chain_mask_5g);
-+ pdev_cap->nss_ratio_enabled =
-+ WMI_NSS_RATIO_EN_DIS_GET(mac_caps->nss_ratio);
-+ pdev_cap->nss_ratio_info =
-+ WMI_NSS_RATIO_INFO_GET(mac_caps->nss_ratio);
- } else {
- return -EINVAL;
- }
-@@ -1059,7 +1063,8 @@ static void ath12k_wmi_put_wmi_channel(s
-
- chan->band_center_freq2 = cpu_to_le32(center_freq1);
-
-- } else if (arg->mode == MODE_11BE_EHT160) {
-+ } else if (arg->mode == MODE_11BE_EHT160 ||
-+ arg->mode == MODE_11AX_HE160) {
- if (arg->freq > center_freq1)
- chan->band_center_freq1 = cpu_to_le32(center_freq1 + 40);
- else
---- a/drivers/net/wireless/ath/ath12k/wmi.h
-+++ b/drivers/net/wireless/ath/ath12k/wmi.h
-@@ -2328,6 +2328,21 @@ enum wmi_direct_buffer_module {
- WMI_DIRECT_BUF_MAX
- };
-
-+/**
-+ * enum wmi_nss_ratio - NSS ratio received from FW during service ready ext event
-+ * @WMI_NSS_RATIO_1BY2_NSS: Max nss of 160MHz is equals to half of the max nss of 80MHz
-+ * @WMI_NSS_RATIO_3BY4_NSS: Max nss of 160MHz is equals to 3/4 of the max nss of 80MHz
-+ * @WMI_NSS_RATIO_1_NSS: Max nss of 160MHz is equals to the max nss of 80MHz
-+ * @WMI_NSS_RATIO_2_NSS: Max nss of 160MHz is equals to two times the max nss of 80MHz
-+ */
-+
-+enum wmi_nss_ratio {
-+ WMI_NSS_RATIO_1BY2_NSS,
-+ WMI_NSS_RATIO_3BY4_NSS,
-+ WMI_NSS_RATIO_1_NSS,
-+ WMI_NSS_RATIO_2_NSS
-+};
-+
- struct ath12k_wmi_pdev_band_arg {
- u32 pdev_id;
- u32 start_freq;
-@@ -2647,6 +2662,12 @@ struct ath12k_wmi_hw_mode_cap_params {
- } __packed;
-
- #define WMI_MAX_HECAP_PHY_SIZE (3)
-+#define WMI_NSS_RATIO_EN_DIS_BITPOS BIT(0)
-+#define WMI_NSS_RATIO_EN_DIS_GET(_val) \
-+ le32_get_bits(_val, WMI_NSS_RATIO_EN_DIS_BITPOS)
-+#define WMI_NSS_RATIO_INFO_BITPOS GENMASK(4, 1)
-+#define WMI_NSS_RATIO_INFO_GET(_val) \
-+ le32_get_bits(_val, WMI_NSS_RATIO_INFO_BITPOS)
-
- /* pdev_id is present in lower 16 bits of pdev_and_hw_link_ids in
- * ath12k_wmi_mac_phy_caps_params & ath12k_wmi_caps_ext_params.
+++ /dev/null
-From patchwork Wed May 21 22:45:39 2025
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Id: 14096122
-Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com
- [205.220.180.131])
- (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
- (No client certificate requested)
- by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9A1E9239E85
-Authentication-Results: smtp.subspace.kernel.org;
- arc=none smtp.client-ip=205.220.180.131
-ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
- t=1747867561; cv=none;
- b=YNQGoLeTsEUX0an1dYT8uFrTBxczoxLPoB0nXP+MEP3YMcemaxVf4zoi5GMSuKPLe4yeLz/R7AB090SrXrBTbY6MmwXLrUJGFBQUGwr05KQ5BnedSLyVE+PtNo01ZVjrjprsc5LC4z0vYHmQdBsqIfqP+bb+ATVkdkkKWV4Kg3A=
-ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
- s=arc-20240116; t=1747867561; c=relaxed/simple;
- bh=WkoD1wqfpiPds2ZNAwn7TY38LnC6cJOAuobqk3tWbSk=;
- h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:
- MIME-Version:Content-Type;
- b=aAO1mDb/PrwqKRHoeS0PAxgJAvDLPWPPBkzRX0hwJbFzcXtKdtWHDE83rjGbjR1bnM7lhkAU4SwoT87sOuciveNqdywUe6+9XTB2oWM/j0Tza/ZRKKRZFeByh7ib8Aibzc4y0ACg7Oaz/QhmWmPObPjc4oKuVzaH/P8Tub0rBcI=
-ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
- dmarc=pass (p=none dis=none) header.from=quicinc.com;
- spf=pass smtp.mailfrom=quicinc.com;
- header.b=o3M+Sjyr; arc=none smtp.client-ip=205.220.180.131
-Authentication-Results: smtp.subspace.kernel.org;
- dmarc=pass (p=none dis=none) header.from=quicinc.com
-Authentication-Results: smtp.subspace.kernel.org;
- spf=pass smtp.mailfrom=quicinc.com
-Authentication-Results: smtp.subspace.kernel.org;
- header.b="o3M+Sjyr"
-Received: from pps.filterd (m0279871.ppops.net [127.0.0.1])
- by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id
- 54LJHZNq001758;
- Wed, 21 May 2025 22:45:56 GMT
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=
- cc:content-transfer-encoding:content-type:date:from:in-reply-to
- :message-id:mime-version:references:subject:to; s=qcppdkim1; bh=
- wh8AVrVaz3Wne8xUCnRodQGPYbrNE8Rm9/NepU3KoQA=; b=o3M+SjyriKBrU+dH
- +Uwb/f5RzskxDlOAgOvwNH7O5p766ueJYE/nAazyAuVI1fbDT1gkgvOM4VOLQAPP
- zg9tDUD5Mz80GzBzSnheYbeedz7RgpaN14Qr6Gz/+1yrP4wWTh2quGduIAXBFDZR
- QpWsQh2DxVOvXqoLRm64iurJNhvpq+YIAwpAxEA9Fp46SrXsFefc82nza6qgdk5P
- pUjalFWnwLLxaSHJj2EoJhFDAf99q9N5KNKW/UCNY8A2CwQXqL9KmggTLRK1OC+S
- ueHigeV9ydoGGD1W6zmEdydGv5JSaQRhjAxtJokUtrlUwn8mbpJyokm+Ie4GZV5v
- tie1qQ==
-Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com
- [129.46.96.20])
- by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwf6vbsg-1
- (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
- Wed, 21 May 2025 22:45:56 +0000 (GMT)
-Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com
- [10.47.209.196])
- by NALASPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id
- 54LMjtcB022245
- (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
- Wed, 21 May 2025 22:45:55 GMT
-Received: from ath12k-linux2.qualcomm.com (10.80.80.8) by
- nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server
- (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
- 15.2.1544.9; Wed, 21 May 2025 15:45:54 -0700
- Pradeep Kumar Chitrapu
-Subject: [PATCH ath-next V14 9/9] wifi: ath12k: add extended NSS bandwidth
- support for 160 MHz
-Date: Wed, 21 May 2025 15:45:39 -0700
-X-Mailer: git-send-email 2.43.0
-Precedence: bulk
-List-Id: <linux-wireless.vger.kernel.org>
-MIME-Version: 1.0
-X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To
- nalasex01a.na.qualcomm.com (10.47.209.196)
-X-QCInternal: smtphost
-X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800
- signatures=585085
-X-Proofpoint-GUID: 3XlPaBNySyE2wx5TC6p1DVWVXzadsV9U
-X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIxMDIyNiBTYWx0ZWRfX4g8vKznbpwuH
- ZKoHe/eZESaXJ/nU0MF27s2mZH9kbhxkG1nYDBAxgIAR6HSB4Ir8V8BP9wvETNPaaV4xpgjbT6m
- sDGIplm3HpwbpmQYiBtQIsOrs/s1B2t7uVdhqW02FHlFu/UIBLwZc7J8sLJcsYdxHYcx7MQ3nEe
- tDoPrPTEwHw7n1CnzcfVsEUAuxuJ5iFaxBATgZF+LuAhijNvhyaoEWRUO2KUcBJaFHq/QbCYfpY
- JBXWUNl+mlZxfQe4pogCpRmvEOONRvpKgZLFdEAxf2Fx0Z7OhaIV84gi99TYTjfe1aihjorJ/cp
- cv78Jzcd3Pe3GwTFD0ZOqI30oSiaUyJS3E9XIjfDGLAVMK6FeM+KOYgnqo95ImgBH8HRshrA4LJ
- qTKv2kKP1y4zPtpf7lmI2mcl7emiLGQx+t0d7Z8upCbYseoNAGHUkFJ45HF940Za9ZkEYTRq
-X-Authority-Analysis: v=2.4 cv=fZOty1QF c=1 sm=1 tr=0 ts=682e57a4 cx=c_pps
- a=ouPCqIW2jiPt+lZRy3xVPw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17
- a=GEpy-HfZoHoA:10 a=dt9VzEwgFbYA:10 a=COk6AnOGAAAA:8 a=Opr4SxZhII4Vei-TI5AA:9
- a=TjNXssC_j7lpFel5tvFf:22
-X-Proofpoint-ORIG-GUID: 3XlPaBNySyE2wx5TC6p1DVWVXzadsV9U
-X-Proofpoint-Virus-Version: vendor=baseguard
- engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40
- definitions=2025-05-21_07,2025-05-20_03,2025-03-28_01
-X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0
- clxscore=1015 mlxscore=0 adultscore=0 spamscore=0 bulkscore=0 suspectscore=0
- malwarescore=0 priorityscore=1501 impostorscore=0 mlxlogscore=999
- lowpriorityscore=0 phishscore=0 classifier=spam authscore=0 authtc=n/a
- authcc= route=outbound adjust=0 reason=mlx scancount=1
- engine=8.19.0-2505160000 definitions=main-2505210226
-
-Currently rx and tx MCS map for 160 MHz under HE capabilities
-are not updating properly, when 160 MHz is configured with NSS
-lesser than max NSS support. Fix this by utilizing
-nss_ratio_enabled and nss_ratio_info fields sent by firmware
-in service ready event.
-
-However, if firmware advertises EXT NSS BW support in VHT caps
-as 1(1x2) and when nss_ratio_info indicates 1:1, reset the EXT
-NSS BW Support in VHT caps to 0 which indicates 1x1. This is
-to avoid incorrectly choosing 1:2 NSS ratio when using the
-default VHT caps advertised by firmware.
-
-Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
-
----
- drivers/net/wireless/ath/ath12k/mac.c | 33 ++++++++++++++++++++++-----
- 1 file changed, 27 insertions(+), 6 deletions(-)
-
---- a/drivers/net/wireless/ath/ath12k/mac.c
-+++ b/drivers/net/wireless/ath/ath12k/mac.c
-@@ -2644,8 +2644,10 @@ static void ath12k_peer_assoc_h_he(struc
- arg->peer_nss = min(link_sta->rx_nss, max_nss);
-
- if (arg->peer_phymode == MODE_11AX_HE160) {
-- tx_nss = ath12k_get_nss_160mhz(ar, max_nss);
-+ tx_nss = ath12k_get_nss_160mhz(ar, ar->num_tx_chains);
- rx_nss = min(arg->peer_nss, tx_nss);
-+
-+ arg->peer_nss = min(link_sta->rx_nss, ar->num_rx_chains);
- arg->peer_bw_rxnss_override = ATH12K_BW_NSS_MAP_ENABLE;
-
- if (!rx_nss) {
-@@ -7465,6 +7467,12 @@ ath12k_create_vht_cap(struct ath12k *ar,
- vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(rxmcs_map);
- vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(txmcs_map);
-
-+ /* Check if the HW supports 1:1 NSS ratio and reset
-+ * EXT NSS BW Support field to 0 to indicate 1:1 ratio
-+ */
-+ if (ar->pdev->cap.nss_ratio_info == WMI_NSS_RATIO_1_NSS)
-+ vht_cap.cap &= ~IEEE80211_VHT_CAP_EXT_NSS_BW_MASK;
-+
- return vht_cap;
- }
-
-@@ -7645,11 +7653,12 @@ static void ath12k_mac_set_hemcsmap(stru
- struct ieee80211_sta_he_cap *he_cap)
- {
- struct ieee80211_he_mcs_nss_supp *mcs_nss = &he_cap->he_mcs_nss_supp;
-- u16 txmcs_map, rxmcs_map;
-+ u8 maxtxnss_160 = ath12k_get_nss_160mhz(ar, ar->num_tx_chains);
-+ u8 maxrxnss_160 = ath12k_get_nss_160mhz(ar, ar->num_rx_chains);
-+ u16 txmcs_map_160 = 0, rxmcs_map_160 = 0;
-+ u16 txmcs_map = 0, rxmcs_map = 0;
- u32 i;
-
-- rxmcs_map = 0;
-- txmcs_map = 0;
- for (i = 0; i < 8; i++) {
- if (i < ar->num_tx_chains &&
- (ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
-@@ -7662,12 +7671,24 @@ static void ath12k_mac_set_hemcsmap(stru
- rxmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
- else
- rxmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
-+
-+ if (i < maxtxnss_160 &&
-+ (ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
-+ txmcs_map_160 |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
-+ else
-+ txmcs_map_160 |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
-+
-+ if (i < maxrxnss_160 &&
-+ (ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
-+ rxmcs_map_160 |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
-+ else
-+ rxmcs_map_160 |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
- }
-
- mcs_nss->rx_mcs_80 = cpu_to_le16(rxmcs_map & 0xffff);
- mcs_nss->tx_mcs_80 = cpu_to_le16(txmcs_map & 0xffff);
-- mcs_nss->rx_mcs_160 = cpu_to_le16(rxmcs_map & 0xffff);
-- mcs_nss->tx_mcs_160 = cpu_to_le16(txmcs_map & 0xffff);
-+ mcs_nss->rx_mcs_160 = cpu_to_le16(rxmcs_map_160 & 0xffff);
-+ mcs_nss->tx_mcs_160 = cpu_to_le16(txmcs_map_160 & 0xffff);
- }
-
- static void ath12k_mac_copy_he_cap(struct ath12k *ar,
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -20,7 +20,7 @@
+@@ -21,7 +21,7 @@
#include <linux/time.h>
#include <linux/bitops.h>
#include <linux/etherdevice.h>
#include <linux/unaligned.h>
#include "hw.h"
-@@ -2718,19 +2718,25 @@ static void ath9k_hw_gpio_cfg_output_mux
+@@ -2719,19 +2719,25 @@ static void ath9k_hw_gpio_cfg_output_mux
static void ath9k_hw_gpio_cfg_soc(struct ath_hw *ah, u32 gpio, bool out,
const char *label)
{
}
static void ath9k_hw_gpio_cfg_wmac(struct ath_hw *ah, u32 gpio, bool out,
-@@ -2792,8 +2798,10 @@ void ath9k_hw_gpio_free(struct ath_hw *a
+@@ -2793,8 +2799,10 @@ void ath9k_hw_gpio_free(struct ath_hw *a
WARN_ON(gpio >= ah->caps.num_gpio_pins);
}
EXPORT_SYMBOL(ath9k_hw_gpio_free);
-@@ -2821,8 +2829,8 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah,
+@@ -2822,8 +2830,8 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah,
val = REG_READ(ah, AR_GPIO_IN(ah)) & BIT(gpio);
else
val = MS_REG_READ(AR, gpio);
} else {
WARN_ON(1);
}
-@@ -2845,8 +2853,8 @@ void ath9k_hw_set_gpio(struct ath_hw *ah
+@@ -2846,8 +2854,8 @@ void ath9k_hw_set_gpio(struct ath_hw *ah
AR7010_GPIO_OUT : AR_GPIO_IN_OUT(ah);
REG_RMW(ah, out_addr, val << gpio, BIT(gpio));
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1434,8 +1434,12 @@ static bool ath9k_hw_set_reset(struct at
+@@ -1435,8 +1435,12 @@ static bool ath9k_hw_set_reset(struct at
if (!AR_SREV_9100(ah))
REG_WRITE(ah, AR_RC, 0);
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1311,39 +1311,56 @@ void ath9k_hw_get_delta_slope_vals(struc
+@@ -1312,39 +1312,56 @@ void ath9k_hw_get_delta_slope_vals(struc
*coef_exponent = coef_exp - 16;
}
return true;
}
-@@ -1396,24 +1413,24 @@ static bool ath9k_hw_set_reset(struct at
+@@ -1397,24 +1414,24 @@ static bool ath9k_hw_set_reset(struct at
rst_flags |= AR_RTC_RC_MAC_COLD;
}
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -2974,7 +2974,8 @@ void ath9k_hw_apply_txpower(struct ath_h
+@@ -2975,7 +2975,8 @@ void ath9k_hw_apply_txpower(struct ath_h
{
struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
struct ieee80211_channel *channel;
u16 ctl = NO_CTL;
if (!chan)
-@@ -2986,9 +2987,14 @@ void ath9k_hw_apply_txpower(struct ath_h
+@@ -2987,9 +2988,14 @@ void ath9k_hw_apply_txpower(struct ath_h
channel = chan->chan;
chan_pwr = min_t(int, channel->max_power * 2, MAX_COMBINED_POWER);
new_pwr = min_t(int, chan_pwr, reg->power_limit);
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -2993,6 +2993,10 @@ void ath9k_hw_apply_txpower(struct ath_h
+@@ -2994,6 +2994,10 @@ void ath9k_hw_apply_txpower(struct ath_h
if (ant_gain > max_gain)
ant_reduction = ant_gain - max_gain;
sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);
--- a/drivers/net/wireless/ath/ath9k/common-debug.c
+++ b/drivers/net/wireless/ath/ath9k/common-debug.c
-@@ -260,3 +260,58 @@ void ath9k_cmn_debug_phy_err(struct dent
+@@ -261,3 +261,58 @@ void ath9k_cmn_debug_phy_err(struct dent
&fops_phy_err);
}
EXPORT_SYMBOL(ath9k_cmn_debug_phy_err);
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -402,13 +402,8 @@ static void ath9k_hw_init_config(struct
+@@ -403,13 +403,8 @@ static void ath9k_hw_init_config(struct
ah->config.rx_intr_mitigation = true;
bool disable_ani;
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
-@@ -297,11 +297,13 @@ EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_ke
+@@ -298,11 +298,13 @@ EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_ke
/*
* Update internal channel flags.
*/
ichan->channel = chan->center_freq;
ichan->chan = chan;
-@@ -309,7 +311,19 @@ static void ath9k_cmn_update_ichannel(st
+@@ -310,7 +312,19 @@ static void ath9k_cmn_update_ichannel(st
if (chan->band == NL80211_BAND_5GHZ)
flags |= CHANNEL_5GHZ;
case NL80211_CHAN_WIDTH_5:
flags |= CHANNEL_QUARTER;
break;
-@@ -342,10 +356,11 @@ struct ath9k_channel *ath9k_cmn_get_chan
+@@ -343,10 +357,11 @@ struct ath9k_channel *ath9k_cmn_get_chan
struct cfg80211_chan_def *chandef)
{
struct ieee80211_channel *curchan = chandef->chan;
}
--- a/drivers/net/wireless/ath/ath9k/common-debug.c
+++ b/drivers/net/wireless/ath/ath9k/common-debug.c
-@@ -315,3 +315,55 @@ void ath9k_cmn_debug_eeprom(struct dentr
+@@ -316,3 +316,55 @@ void ath9k_cmn_debug_eeprom(struct dentr
&fops_eeprom);
}
EXPORT_SYMBOL(ath9k_cmn_debug_eeprom);
+
+ common->chan_bw = chan_bw;
+ if (!test_bit(ATH_OP_INVALID, &common->op_flags))
-+ common->ieee_ops->config(ah->hw, IEEE80211_CONF_CHANGE_CHANNEL);
++ common->ieee_ops->config(ah->hw, -1, IEEE80211_CONF_CHANGE_CHANNEL);
+
+ return count;
+}
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -662,6 +662,7 @@ int ath9k_hw_init(struct ath_hw *ah)
+@@ -663,6 +663,7 @@ int ath9k_hw_init(struct ath_hw *ah)
/* These are all the AR5008/AR9001/AR9002/AR9003 hardware family of chipsets */
switch (ah->hw_version.devid) {
struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1872,6 +1872,20 @@ u32 ath9k_hw_get_tsf_offset(ktime_t last
+@@ -1873,6 +1873,20 @@ u32 ath9k_hw_get_tsf_offset(ktime_t last
}
EXPORT_SYMBOL(ath9k_hw_get_tsf_offset);
int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
struct ath9k_hw_cal_data *caldata, bool fastcc)
{
-@@ -2080,6 +2094,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -2081,6 +2095,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
ar9003_hw_disable_phy_restart(ah);
ath9k_hw_apply_gpio_override(ah);
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -247,6 +247,19 @@ void ath9k_hw_get_channel_centers(struct
+@@ -248,6 +248,19 @@ void ath9k_hw_get_channel_centers(struct
centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT);
}
/******************/
/* Chip Revisions */
/******************/
-@@ -1454,6 +1467,9 @@ static bool ath9k_hw_set_reset(struct at
+@@ -1455,6 +1468,9 @@ static bool ath9k_hw_set_reset(struct at
udelay(50);
}
return true;
}
-@@ -1553,6 +1569,9 @@ static bool ath9k_hw_chip_reset(struct a
+@@ -1554,6 +1570,9 @@ static bool ath9k_hw_chip_reset(struct a
ar9003_hw_internal_regulator_apply(ah);
ath9k_hw_init_pll(ah, chan);
return true;
}
-@@ -1859,8 +1878,14 @@ static int ath9k_hw_do_fastcc(struct ath
+@@ -1860,8 +1879,14 @@ static int ath9k_hw_do_fastcc(struct ath
if (AR_SREV_9271(ah))
ar9002_hw_load_ani_reg(ah, chan);
return -EINVAL;
}
-@@ -2105,6 +2130,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -2106,6 +2131,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
ath9k_hw_set_radar_params(ah);
}
--- a/local-symbols
+++ b/local-symbols
-@@ -117,6 +117,7 @@ ATH9K_WOW=
+@@ -118,6 +118,7 @@ ATH9K_WOW=
ATH9K_RFKILL=
ATH9K_CHANNEL_CONTEXT=
ATH9K_PCOEM=
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/ahb.c
-+++ b/drivers/net/wireless/ath/ath9k/ahb.c
-@@ -16,37 +16,21 @@
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-+#include <linux/mod_devicetable.h>
-+#include <linux/module.h>
- #include <linux/nl80211.h>
-+#include <linux/of.h>
- #include <linux/platform_device.h>
--#include <linux/module.h>
--#include <linux/mod_devicetable.h>
-+
- #include "ath9k.h"
-
--static const struct platform_device_id ath9k_platform_id_table[] = {
-- {
-- .name = "ath9k",
-- .driver_data = AR5416_AR9100_DEVID,
-- },
-- {
-- .name = "ar933x_wmac",
-- .driver_data = AR9300_DEVID_AR9330,
-- },
-- {
-- .name = "ar934x_wmac",
-- .driver_data = AR9300_DEVID_AR9340,
-- },
-- {
-- .name = "qca955x_wmac",
-- .driver_data = AR9300_DEVID_QCA955X,
-- },
-- {
-- .name = "qca953x_wmac",
-- .driver_data = AR9300_DEVID_AR953X,
-- },
-- {
-- .name = "qca956x_wmac",
-- .driver_data = AR9300_DEVID_QCA956X,
-- },
-+static const struct of_device_id ath9k_of_match_table[] = {
-+ { .compatible = "qca,ar9130-wifi", .data = (void *)AR5416_AR9100_DEVID },
-+ { .compatible = "qca,ar9330-wifi", .data = (void *)AR9300_DEVID_AR9330 },
-+ { .compatible = "qca,ar9340-wifi", .data = (void *)AR9300_DEVID_AR9340 },
-+ { .compatible = "qca,qca9530-wifi", .data = (void *)AR9300_DEVID_AR953X },
-+ { .compatible = "qca,qca9550-wifi", .data = (void *)AR9300_DEVID_QCA955X },
-+ { .compatible = "qca,qca9560-wifi", .data = (void *)AR9300_DEVID_QCA956X },
- {},
- };
-
-@@ -71,19 +55,14 @@ static const struct ath_bus_ops ath_ahb_
-
- static int ath_ahb_probe(struct platform_device *pdev)
- {
-- void __iomem *mem;
-- struct ath_softc *sc;
- struct ieee80211_hw *hw;
-- const struct platform_device_id *id = platform_get_device_id(pdev);
-- int irq;
-- int ret = 0;
-+ struct ath_softc *sc;
- struct ath_hw *ah;
-+ void __iomem *mem;
- char hw_name[64];
--
-- if (!dev_get_platdata(&pdev->dev)) {
-- dev_err(&pdev->dev, "no platform data specified\n");
-- return -EINVAL;
-- }
-+ u16 dev_id;
-+ int irq;
-+ int ret;
-
- mem = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(mem)) {
-@@ -117,7 +96,8 @@ static int ath_ahb_probe(struct platform
- goto err_free_hw;
- }
-
-- ret = ath9k_init_device(id->driver_data, sc, &ath_ahb_bus_ops);
-+ dev_id = (u16)(kernel_ulong_t)of_device_get_match_data(&pdev->dev);
-+ ret = ath9k_init_device(dev_id, sc, &ath_ahb_bus_ops);
- if (ret) {
- dev_err(&pdev->dev, "failed to initialize device\n");
- goto err_irq;
-@@ -167,11 +147,11 @@ static struct platform_driver ath_ahb_dr
-
- .driver = {
- .name = "ath9k",
-+ .of_match_table = ath9k_of_match_table,
- },
-- .id_table = ath9k_platform_id_table,
- };
-
--MODULE_DEVICE_TABLE(platform, ath9k_platform_id_table);
-+MODULE_DEVICE_TABLE(of, ath9k_of_match_table);
-
- int ath_ahb_init(void)
- {
if (wl->radio_enabled != phy->radio_on) {
if (wl->radio_enabled) {
-@@ -5178,6 +5175,47 @@ static int b43_op_get_survey(struct ieee
+@@ -5178,6 +5175,49 @@ static int b43_op_get_survey(struct ieee
return 0;
}
-+static int b43_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
++static int b43_op_set_antenna(struct ieee80211_hw *hw, int radio_idx,
++ u32 tx_ant, u32 rx_ant)
+{
+ struct b43_wl *wl = hw_to_b43_wl(hw);
+ struct b43_wldev *dev = wl->current_dev;
+}
+
+
-+static int b43_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
++static int b43_op_get_antenna(struct ieee80211_hw *hw, int radio_idx,
++ u32 *tx_ant, u32 *rx_ant)
+{
+ struct b43_wl *wl = hw_to_b43_wl(hw);
+ struct b43_wldev *dev = wl->current_dev;
static const struct ieee80211_ops b43_hw_ops = {
.add_chanctx = ieee80211_emulate_add_chanctx,
.remove_chanctx = ieee80211_emulate_remove_chanctx,
-@@ -5204,6 +5242,8 @@ static const struct ieee80211_ops b43_hw
+@@ -5204,6 +5244,8 @@ static const struct ieee80211_ops b43_hw
.sw_scan_complete = b43_op_sw_scan_complete_notifier,
.get_survey = b43_op_get_survey,
.rfkill_poll = b43_rfkill_poll,
};
/* Hard-reset the chip. Do not call this directly.
-@@ -5505,6 +5545,8 @@ static int b43_one_core_attach(struct b4
+@@ -5505,6 +5547,8 @@ static int b43_one_core_attach(struct b4
if (!wldev)
goto out;
wldev->use_pio = b43_modparam_pio;
wldev->dev = dev;
wldev->wl = wl;
-@@ -5596,6 +5638,9 @@ static struct b43_wl *b43_wireless_init(
+@@ -5596,6 +5640,9 @@ static struct b43_wl *b43_wireless_init(
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
+++ /dev/null
-Subject: [PATCH] brcmfmac: add in-driver tables with country codes
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This adds early support for changing region. Ideally this data should
-be stored in DT as all these mappings are devices specific.
-
----
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
-@@ -66,6 +66,36 @@ static int brcmf_of_get_country_codes(st
- return 0;
- }
-
-+/* TODO: FIXME: Use DT */
-+static void brcmf_of_probe_cc(struct device *dev,
-+ struct brcmf_mp_device *settings)
-+{
-+ static struct brcmfmac_pd_cc_entry netgear_r8000_cc_ent[] = {
-+ { "JP", "JP", 78 },
-+ { "US", "Q2", 86 },
-+ };
-+ struct brcmfmac_pd_cc_entry *cc_ent = NULL;
-+ int table_size = 0;
-+
-+ if (of_machine_is_compatible("netgear,r8000")) {
-+ cc_ent = netgear_r8000_cc_ent;
-+ table_size = ARRAY_SIZE(netgear_r8000_cc_ent);
-+ }
-+
-+ if (cc_ent && table_size) {
-+ struct brcmfmac_pd_cc *cc;
-+ size_t memsize;
-+
-+ memsize = table_size * sizeof(struct brcmfmac_pd_cc_entry);
-+ cc = devm_kzalloc(dev, sizeof(*cc) + memsize, GFP_KERNEL);
-+ if (!cc)
-+ return;
-+ cc->table_size = table_size;
-+ memcpy(cc->table, cc_ent, memsize);
-+ settings->country_codes = cc;
-+ }
-+}
-+
- int brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
- struct brcmf_mp_device *settings)
- {
-@@ -121,6 +151,8 @@ int brcmf_of_probe(struct device *dev, e
-
- brcmf_dbg(INFO, "%s LPO clock\n", clk ? "enable" : "no");
-
-+ brcmf_of_probe_cc(dev, settings);
-+
- if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac"))
- return 0;
-
#include <net/cfg80211.h>
#include <net/netlink.h>
#include <uapi/linux/if_arp.h>
-@@ -8223,31 +8224,45 @@ static void brcmf_cfg80211_reg_notifier(
+@@ -8270,31 +8271,45 @@ static void brcmf_cfg80211_reg_notifier(
struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
struct brcmf_pub *drvr = cfg->pub;
struct brcmf_fil_country_le ccreq;
/**
* struct nvram_parser - internal info for parser.
*
-@@ -562,11 +565,27 @@ static int brcmf_fw_request_nvram_done(c
- goto fail;
+@@ -566,11 +569,27 @@ static int brcmf_fw_request_nvram_done(c
+ }
}
- if (data)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -3343,6 +3343,7 @@ brcmf_cfg80211_set_power_mgmt(struct wip
+@@ -3360,6 +3360,7 @@ brcmf_cfg80211_set_power_mgmt(struct wip
bphy_err(drvr, "error (%d)\n", err);
}
BRCMF_DEFAULT_SCAN_CHANNEL_TIME);
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -1322,7 +1322,7 @@ int brcmf_alloc(struct device *dev, stru
+@@ -1327,7 +1327,7 @@ int brcmf_alloc(struct device *dev, stru
return 0;
}
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_pub *drvr = bus_if->drvr;
-@@ -1365,10 +1365,13 @@ int brcmf_attach(struct device *dev)
+@@ -1370,10 +1370,13 @@ int brcmf_attach(struct device *dev)
brcmf_fwvid_get_cfg80211_ops(drvr);
void *data);
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-@@ -2210,7 +2210,7 @@ static void brcmf_pcie_setup(struct devi
+@@ -2214,7 +2214,7 @@ static void brcmf_pcie_setup(struct devi
init_waitqueue_head(&devinfo->mbdata_resp_wait);
#ifdef DEBUG
/* Device console log buffer state */
-@@ -1105,7 +1117,7 @@ static void brcmf_sdio_get_console_addr(
+@@ -1106,7 +1118,7 @@ static void brcmf_sdio_get_console_addr(
}
#endif /* DEBUG */
{
struct brcmf_sdio_dev *sdiod = bus->sdiodev;
struct brcmf_core *core = bus->sdio_core;
-@@ -1194,6 +1206,9 @@ static u32 brcmf_sdio_hostmail(struct br
+@@ -1195,6 +1207,9 @@ static u32 brcmf_sdio_hostmail(struct br
HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK))
brcmf_err("Unknown mailbox data content: 0x%02x\n",
hmb_data);
return intstatus;
}
-@@ -2580,6 +2595,182 @@ static int brcmf_sdio_intr_rstatus(struc
+@@ -2581,6 +2596,182 @@ static int brcmf_sdio_intr_rstatus(struc
return ret;
}
static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
{
struct brcmf_sdio_dev *sdiod = bus->sdiodev;
-@@ -2651,8 +2842,11 @@ static void brcmf_sdio_dpc(struct brcmf_
+@@ -2652,8 +2843,11 @@ static void brcmf_sdio_dpc(struct brcmf_
/* Handle host mailbox indication */
if (intstatus & I_HMB_HOST_INT) {
}
sdio_release_host(bus->sdiodev->func1);
-@@ -2697,7 +2891,7 @@ static void brcmf_sdio_dpc(struct brcmf_
+@@ -2698,7 +2892,7 @@ static void brcmf_sdio_dpc(struct brcmf_
brcmf_sdio_clrintr(bus);
if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) &&
sdio_claim_host(bus->sdiodev->func1);
if (bus->ctrl_frame_stat) {
err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf,
-@@ -3567,6 +3761,10 @@ static int brcmf_sdio_bus_preinit(struct
+@@ -3569,6 +3763,10 @@ static int brcmf_sdio_bus_preinit(struct
if (err < 0)
goto done;
bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN;
if (sdiodev->sg_support) {
bus->txglom = false;
-@@ -4217,7 +4415,7 @@ static void brcmf_sdio_firmware_callback
+@@ -4219,7 +4417,7 @@ static void brcmf_sdio_firmware_callback
u8 saveclk, bpreq;
u8 devctl;
if (err)
goto fail;
-@@ -4394,12 +4592,25 @@ static void brcmf_sdio_firmware_callback
+@@ -4397,12 +4595,25 @@ static void brcmf_sdio_firmware_callback
}
/* Attach to the common layer, reserve hdr space */
/* ready */
return;
-@@ -4646,3 +4857,40 @@ int brcmf_sdio_sleep(struct brcmf_sdio *
+@@ -4649,3 +4860,40 @@ int brcmf_sdio_sleep(struct brcmf_sdio *
return ret;
}
#endif /* BRCMFMAC_SDIO_H */
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-@@ -1211,7 +1211,7 @@ static void brcmf_usb_probe_phase2(struc
+@@ -1208,7 +1208,7 @@ static void brcmf_usb_probe_phase2(struc
goto error;
/* Attach to the common driver interface */
if (ret)
goto error;
-@@ -1291,7 +1291,7 @@ static int brcmf_usb_probe_cb(struct brc
+@@ -1288,7 +1288,7 @@ static int brcmf_usb_probe_cb(struct brc
ret = brcmf_alloc(devinfo->dev, devinfo->settings);
if (ret)
goto fail;
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -2496,43 +2496,50 @@ brcmf_cfg80211_connect(struct wiphy *wip
+@@ -2512,43 +2512,50 @@ brcmf_cfg80211_connect(struct wiphy *wip
goto done;
}
err = brcmf_fil_bsscfg_data_set(vif->ifp, "actframe_abort", &int_val,
sizeof(s32));
if (err)
-@@ -1826,6 +1830,7 @@ bool brcmf_p2p_send_action_frame(struct
+@@ -1817,6 +1821,7 @@ bool brcmf_p2p_send_action_frame(struct
/* validate channel and p2p ies */
if (config_af_params.search_channel &&
IS_P2P_SOCIAL_CHANNEL(le32_to_cpu(af_params->channel)) &&
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -8002,6 +8002,7 @@ static s32 brcmf_translate_country_code(
+@@ -8049,6 +8049,7 @@ static s32 brcmf_translate_country_code(
return 0;
}
static int
brcmf_parse_dump_obss(char *buf, struct brcmf_dump_survey *survey)
{
-@@ -8224,6 +8225,7 @@ exit:
+@@ -8271,6 +8272,7 @@ exit:
brcmf_set_mpc(ifp, 1);
return err;
}
static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,
struct regulatory_request *req)
-@@ -8390,8 +8392,10 @@ struct brcmf_cfg80211_info *brcmf_cfg802
+@@ -8437,8 +8439,10 @@ struct brcmf_cfg80211_info *brcmf_cfg802
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK))
ops->set_rekey_data = brcmf_cfg80211_set_rekey_data;
#endif
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
-@@ -446,7 +446,11 @@ TRACE_EVENT(rdev_add_virtual_intf,
+@@ -478,7 +478,11 @@ TRACE_EVENT(rdev_add_virtual_intf,
),
TP_fast_assign(
WIPHY_ASSIGN;
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
-@@ -1638,10 +1638,10 @@ static int ath10k_fw_init(struct ath10k
+@@ -1630,10 +1630,10 @@ static int ath10k_fw_init(struct ath10k
ar_snoc->fw.dev = &pdev->dev;
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
-@@ -1031,10 +1031,10 @@ static int ath11k_ahb_fw_resources_init(
+@@ -1020,10 +1020,10 @@ static int ath11k_ahb_fw_resources_init(
ab_ahb->fw.dev = &pdev->dev;
}
return err;
-@@ -1521,7 +1537,11 @@ static int cfg80211_netdev_notifier_call
+@@ -1549,7 +1565,11 @@ static int cfg80211_netdev_notifier_call
SET_NETDEV_DEVTYPE(dev, &wiphy_type);
wdev->netdev = dev;
/* can only change netns with wiphy */
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-@@ -1588,7 +1588,11 @@ static int brcmf_usb_reset_device(struct
+@@ -1585,7 +1585,11 @@ static int brcmf_usb_reset_device(struct
void brcmf_usb_exit(void)
{
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
-@@ -6672,6 +6672,7 @@ static void hwsim_virtio_rx_done(struct
+@@ -6927,6 +6927,7 @@ static void hwsim_virtio_rx_done(struct
static int init_vqs(struct virtio_device *vdev)
{
struct virtqueue_info vqs_info[HWSIM_NUM_VQS] = {
[HWSIM_VQ_TX] = { "tx", hwsim_virtio_tx_done },
[HWSIM_VQ_RX] = { "rx", hwsim_virtio_rx_done },
-@@ -6679,6 +6680,19 @@ static int init_vqs(struct virtio_device
+@@ -6934,6 +6935,19 @@ static int init_vqs(struct virtio_device
return virtio_find_vqs(vdev, HWSIM_NUM_VQS,
hwsim_vqs, vqs_info, NULL);
+++ /dev/null
---- a/drivers/net/wireless/ti/wlcore/sysfs.c
-+++ b/drivers/net/wireless/ti/wlcore/sysfs.c
-@@ -88,7 +88,7 @@ static ssize_t hw_pg_ver_show(struct dev
- static DEVICE_ATTR_RO(hw_pg_ver);
-
- static ssize_t wl1271_sysfs_read_fwlog(struct file *filp, struct kobject *kobj,
-- const struct bin_attribute *bin_attr,
-+ struct bin_attribute *bin_attr,
- char *buffer, loff_t pos, size_t count)
- {
- struct device *dev = kobj_to_dev(kobj);
-@@ -121,7 +121,7 @@ static ssize_t wl1271_sysfs_read_fwlog(s
-
- static const struct bin_attribute fwlog_attr = {
- .attr = { .name = "fwlog", .mode = 0400 },
-- .read_new = wl1271_sysfs_read_fwlog,
-+ .read = wl1271_sysfs_read_fwlog,
- };
-
- int wlcore_sysfs_init(struct wl1271 *wl)
.llseek = generic_file_llseek, \
};
-@@ -141,9 +142,10 @@ static ssize_t aqm_write(struct file *fi
+@@ -139,9 +140,10 @@ static ssize_t aqm_write(struct file *fi
return -EINVAL;
}
.llseek = default_llseek,
};
-@@ -192,9 +194,10 @@ static ssize_t airtime_flags_write(struc
+@@ -190,9 +192,10 @@ static ssize_t airtime_flags_write(struc
return count;
}
.llseek = default_llseek,
};
-@@ -222,8 +225,9 @@ static ssize_t aql_pending_read(struct f
+@@ -220,8 +223,9 @@ static ssize_t aql_pending_read(struct f
buf, len);
}
.llseek = default_llseek,
};
-@@ -301,9 +305,10 @@ static ssize_t aql_txq_limit_write(struc
+@@ -299,9 +303,10 @@ static ssize_t aql_txq_limit_write(struc
return count;
}
.llseek = default_llseek,
};
-@@ -350,9 +355,10 @@ static ssize_t aql_enable_write(struct f
+@@ -348,9 +353,10 @@ static ssize_t aql_enable_write(struct f
return count;
}
.llseek = default_llseek,
};
-@@ -400,9 +406,10 @@ static ssize_t force_tx_status_write(str
+@@ -398,9 +404,10 @@ static ssize_t force_tx_status_write(str
return count;
}
.llseek = default_llseek,
};
-@@ -427,8 +434,9 @@ static ssize_t reset_write(struct file *
+@@ -425,8 +432,9 @@ static ssize_t reset_write(struct file *
return count;
}
.llseek = noop_llseek,
};
#endif
-@@ -656,8 +664,9 @@ static ssize_t stats_ ##name## _read(str
+@@ -653,8 +661,9 @@ static ssize_t stats_ ##name## _read(str
print_devstats_##name); \
} \
\
.llseek = generic_file_llseek, \
}
-@@ -442,8 +444,9 @@ STA_OPS_RW(agg_status);
+@@ -440,8 +442,9 @@ STA_OPS_RW(agg_status);
/* link sta attributes */
#define LINK_STA_OPS(name) \
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
-@@ -249,8 +249,9 @@ static ssize_t rcname_read(struct file *
+@@ -252,8 +252,9 @@ static ssize_t rcname_read(struct file *
ref->ops->name, len);
}
+++ /dev/null
-From f4e661a75cdfa7eb88ac0fa832edd4a90775805d Mon Sep 17 00:00:00 2001
-Date: Fri, 7 Nov 2025 23:05:56 +0100
-Subject: [PATCH] mwl8k: inject DS Params IE into beacons if missing
-
-Some Marvell AP firmware used with mwl8k misbehaves when beacon frames
-do not contain a WLAN_EID_DS_PARAMS information element with the current
-channel. It was reported on OpenWrt Github issues [0].
-
-When hostapd/mac80211 omits DS Params from the beacon (which is valid on
-some bands), the firmware stops transmitting sane frames and RX status
-starts reporting bogus channel information. This makes AP mode unusable.
-
-Newer Marvell drivers (mwlwifi [1]) hard-code DS Params IE into AP beacons
-for all chips, which suggests this is a firmware requirement rather than
-a mwl8k-specific quirk.
-
-Mirror that behaviour in mwl8k: when setting the beacon, check if
-WLAN_EID_DS_PARAMS is present, and if not, extend the beacon and inject
-a DS Params IE at the beginning of the IE list, using the current
-channel from hw->conf.chandef.chan.
-
-Tested on Linksys EA4500 (88W8366).
-
-[0] https://github.com/openwrt/openwrt/issues/19088
-[1] https://github.com/kaloz/mwlwifi/blob/db97edf20fadea2617805006f5230665fadc6a8c/hif/fwcmd.c#L675
-
----
- drivers/net/wireless/marvell/mwl8k.c | 61 +++++++++++++++++++++++++---
- 1 file changed, 56 insertions(+), 5 deletions(-)
-
---- a/drivers/net/wireless/marvell/mwl8k.c
-+++ b/drivers/net/wireless/marvell/mwl8k.c
-@@ -2962,6 +2962,42 @@ mwl8k_cmd_rf_antenna(struct ieee80211_hw
- /*
- * CMD_SET_BEACON.
- */
-+
-+static bool mwl8k_beacon_has_ds_params(const u8 *buf, int len)
-+{
-+ const struct ieee80211_mgmt *mgmt = (const void *)buf;
-+ int ies_len;
-+
-+ if (len <= offsetof(struct ieee80211_mgmt, u.beacon.variable))
-+ return false;
-+
-+ ies_len = len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
-+
-+ return cfg80211_find_ie(WLAN_EID_DS_PARAMS, mgmt->u.beacon.variable,
-+ ies_len) != NULL;
-+}
-+
-+static void mwl8k_beacon_copy_inject_ds_params(struct ieee80211_hw *hw,
-+ u8 *buf_dst, const u8 *buf_src,
-+ int src_len)
-+{
-+ const struct ieee80211_mgmt *mgmt = (const void *)buf_src;
-+ const u8 *ies;
-+ int hdr_len, left;
-+
-+ ies = mgmt->u.beacon.variable;
-+ hdr_len = ies - buf_src;
-+ left = src_len - hdr_len;
-+
-+ memcpy(buf_dst, buf_src, hdr_len);
-+
-+ /* Inject a DS Params IE at the beginning of the IE list */
-+ buf_dst[hdr_len + 0] = WLAN_EID_DS_PARAMS;
-+ buf_dst[hdr_len + 1] = 1;
-+ buf_dst[hdr_len + 2] = hw->conf.chandef.chan->hw_value;
-+
-+ memcpy(buf_dst + hdr_len + 3, buf_src + hdr_len, left);
-+}
- struct mwl8k_cmd_set_beacon {
- struct mwl8k_cmd_pkt_hdr header;
- __le16 beacon_len;
-@@ -2971,17 +3007,32 @@ struct mwl8k_cmd_set_beacon {
- static int mwl8k_cmd_set_beacon(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, u8 *beacon, int len)
- {
-+ bool ds_params_present = mwl8k_beacon_has_ds_params(beacon, len);
- struct mwl8k_cmd_set_beacon *cmd;
-- int rc;
-+ int rc, final_len = len;
-+
-+ if (!ds_params_present)
-+ /*
-+ * mwl8k firmware requires a DS Params IE with the current
-+ * channel in AP beacons. If mac80211/hostapd does not
-+ * include it, inject one here. IE ID + length + channel
-+ * number = 3 bytes.
-+ */
-+ final_len += 3;
-
-- cmd = kzalloc(sizeof(*cmd) + len, GFP_KERNEL);
-+ cmd = kzalloc(sizeof(*cmd) + final_len, GFP_KERNEL);
- if (cmd == NULL)
- return -ENOMEM;
-
- cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_BEACON);
-- cmd->header.length = cpu_to_le16(sizeof(*cmd) + len);
-- cmd->beacon_len = cpu_to_le16(len);
-- memcpy(cmd->beacon, beacon, len);
-+ cmd->header.length = cpu_to_le16(sizeof(*cmd) + final_len);
-+ cmd->beacon_len = cpu_to_le16(final_len);
-+
-+ if (ds_params_present)
-+ memcpy(cmd->beacon, beacon, len);
-+ else
-+ mwl8k_beacon_copy_inject_ds_params(hw, cmd->beacon, beacon,
-+ len);
-
- rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
- kfree(cmd);
--- a/drivers/net/wireless/marvell/mwl8k.c
+++ b/drivers/net/wireless/marvell/mwl8k.c
-@@ -5763,6 +5763,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
+@@ -5779,6 +5779,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
static const struct pci_device_id mwl8k_pci_id_table[] = {
--- a/drivers/net/wireless/marvell/libertas/cfg.c
+++ b/drivers/net/wireless/marvell/libertas/cfg.c
-@@ -2102,6 +2102,8 @@ struct wireless_dev *lbs_cfg_alloc(struc
+@@ -2105,6 +2105,8 @@ struct wireless_dev *lbs_cfg_alloc(struc
goto err_wiphy_new;
}
--- a/drivers/net/wireless/marvell/libertas/cfg.c
+++ b/drivers/net/wireless/marvell/libertas/cfg.c
-@@ -2179,6 +2179,8 @@ int lbs_cfg_register(struct lbs_private
+@@ -2182,6 +2182,8 @@ int lbs_cfg_register(struct lbs_private
wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
wdev->wiphy->reg_notifier = lbs_reg_notifier;
--- a/drivers/net/wireless/marvell/mwl8k.c
+++ b/drivers/net/wireless/marvell/mwl8k.c
-@@ -6349,6 +6349,8 @@ static int mwl8k_probe(struct pci_dev *p
+@@ -6365,6 +6365,8 @@ static int mwl8k_probe(struct pci_dev *p
priv->running_bsses = 0;
return rc;
err_stop_firmware:
-@@ -6382,8 +6384,6 @@ static void mwl8k_remove(struct pci_dev
+@@ -6398,8 +6400,6 @@ static void mwl8k_remove(struct pci_dev
return;
priv = hw->priv;
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
-@@ -1090,6 +1090,8 @@ void mwifiex_cancel_all_pending_cmd(stru
+@@ -1091,6 +1091,8 @@ void mwifiex_cancel_all_pending_cmd(stru
void mwifiex_cancel_pending_scan_cmd(struct mwifiex_adapter *adapter);
void mwifiex_cancel_scan(struct mwifiex_adapter *adapter);
--- a/drivers/net/wireless/ralink/rt2x00/Kconfig
+++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
-@@ -226,36 +226,37 @@ config RT2800SOC
+@@ -223,33 +223,33 @@ config RT2800SOC
config RT2800_LIB
- tristate
+ tristate "RT2800 USB/PCI support"
depends on m
+ depends on CRC_CCITT
config RT2800_LIB_MMIO
- tristate
- tristate
+ tristate "RT2x00 MMIO support"
depends on m
+ select RT2X00_LIB
config RT2X00_LIB_PCI
- tristate
depends on m
select RT2X00_LIB
- config RT2X00_LIB_SOC
-- tristate
-+ tristate "RT2x00 SoC support"
-+ depends on SOC_RT288X || SOC_RT305X || SOC_MT7620
- depends on m
- select RT2X00_LIB
-
config RT2X00_LIB_USB
- tristate
+ tristate "RT2x00 USB support"
--- a/drivers/net/wireless/ralink/rt2x00/Kconfig
+++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
-@@ -211,7 +211,7 @@ endif
+@@ -209,7 +209,7 @@ endif
config RT2800SOC
tristate "Ralink WiSoC support"
depends on m
-- depends on SOC_RT288X || SOC_RT305X || SOC_MT7620
-+ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620
- select RT2X00_LIB_SOC
+- depends on OF && (SOC_RT288X || SOC_RT305X || SOC_MT7620 || COMPILE_TEST)
++ depends on OF && (SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620 || COMPILE_TEST)
select RT2X00_LIB_MMIO
select RT2X00_LIB_CRYPTO
-@@ -246,7 +246,7 @@ config RT2X00_LIB_PCI
-
- config RT2X00_LIB_SOC
- tristate "RT2x00 SoC support"
-- depends on SOC_RT288X || SOC_RT305X || SOC_MT7620
-+ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620
- depends on m
- select RT2X00_LIB
-
+ select RT2X00_LIB_FIRMWARE
drivers/net/wireless/ralink/rt2x00/rt2x00.h | 1 +
.../net/wireless/ralink/rt2x00/rt2x00dev.c | 9 +++
.../net/wireless/ralink/rt2x00/rt2x00eeprom.c | 75 +++++++++++++++++++
- .../net/wireless/ralink/rt2x00/rt2x00soc.c | 1 +
- .../net/wireless/ralink/rt2x00/rt2x00soc.h | 9 +++
+ .../net/wireless/ralink/rt2x00/rt2800soc.c | 1 +
+ .../net/wireless/ralink/rt2x00/rt2800soc.h | 9 +++
8 files changed, 102 insertions(+), 14 deletions(-)
create mode 100644 drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
select RT2X00_LIB_FIRMWARE
+ select RT2X00_LIB_EEPROM
select RT2X00_LIB_CRYPTO
- depends on CRC_CCITT
depends on EEPROM_93CX6
-@@ -216,6 +217,7 @@ config RT2800SOC
+ help
+@@ -213,6 +214,7 @@ config RT2800SOC
select RT2X00_LIB_MMIO
select RT2X00_LIB_CRYPTO
select RT2X00_LIB_FIRMWARE
select RT2800_LIB
select RT2800_LIB_MMIO
help
-@@ -266,6 +268,9 @@ config RT2X00_LIB_FIRMWARE
+@@ -259,6 +261,9 @@ config RT2X00_LIB_FIRMWARE
config RT2X00_LIB_CRYPTO
bool
/* Firmware functions */
static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev)
{
-@@ -172,7 +159,7 @@ static const struct rt2800_ops rt2800soc
+@@ -190,7 +177,7 @@ static const struct rt2800_ops rt2800soc
.register_multiread = rt2x00mmio_register_multiread,
.register_multiwrite = rt2x00mmio_register_multiwrite,
.regbusy_read = rt2x00mmio_regbusy_read,
.hwcrypt_disabled = rt2800soc_hwcrypt_disabled,
.drv_write_firmware = rt2800soc_write_firmware,
.drv_init_registers = rt2800mmio_init_registers,
+@@ -304,6 +291,7 @@ static int rt2x00soc_probe(struct platfo
+ rt2x00dev->name = pdev->dev.driver->name;
+ rt2x00dev->csr.base = mem;
+
++ set_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags);
+ rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
+
+ retval = rt2x00lib_probe_dev(rt2x00dev);
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -692,6 +692,7 @@ enum rt2x00_capability_flags {
/*
* Capabilities
-@@ -1504,4 +1505,13 @@ void rt2x00lib_remove_dev(struct rt2x00_
+@@ -1506,4 +1507,13 @@ void rt2x00lib_remove_dev(struct rt2x00_
int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev);
int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev);
#endif /* RT2X00_H */
--- /dev/null
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
-@@ -0,0 +1,79 @@
+@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <linux/of.h>
+
+#include "rt2x00.h"
-+#include "rt2x00soc.h"
+
+static const char *
+rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
+ return rt2x00lib_read_eeprom_file(rt2x00dev);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_read_eeprom);
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c
-@@ -86,6 +86,7 @@ int rt2x00soc_probe(struct platform_devi
- if (IS_ERR(rt2x00dev->clk))
- rt2x00dev->clk = NULL;
-
-+ set_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags);
- rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
-
- retval = rt2x00soc_alloc_reg(rt2x00dev);
--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
@@ -278,6 +278,9 @@ static int rt2800pci_read_eeprom(struct
--- a/drivers/net/wireless/ralink/rt2x00/Kconfig
+++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
-@@ -220,6 +220,7 @@ config RT2800SOC
+@@ -217,6 +217,7 @@ config RT2800SOC
select RT2X00_LIB_EEPROM
select RT2800_LIB
select RT2800_LIB_MMIO
Supported chips: RT2880, RT3050, RT3052, RT3350, RT3352.
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
-@@ -11,10 +11,66 @@
+@@ -11,9 +11,65 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
+#endif
#include "rt2x00.h"
- #include "rt2x00soc.h"
+#if IS_ENABLED(CONFIG_MTD)
+static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev)
static const char *
rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
{
-@@ -74,6 +130,14 @@ err_exit:
+@@ -73,6 +129,14 @@ err_exit:
int rt2x00lib_read_eeprom(struct rt2x00_dev *rt2x00dev)
{
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
-@@ -20,6 +20,19 @@
- #include "rt2x00soc.h"
+@@ -19,6 +19,19 @@
+ #include "rt2x00.h"
#if IS_ENABLED(CONFIG_MTD)
+static void rt2800lib_eeprom_swap(struct rt2x00_dev *rt2x00dev)
static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev)
{
struct device_node *np = rt2x00dev->dev->of_node, *mtd_np = NULL;
-@@ -65,6 +78,8 @@ static int rt2800lib_read_eeprom_mtd(str
+@@ -64,6 +77,8 @@ static int rt2800lib_read_eeprom_mtd(str
return ret;
}
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
-@@ -15,11 +15,11 @@
+@@ -15,10 +15,10 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#endif
+#include <linux/nvmem-consumer.h>
#include "rt2x00.h"
- #include "rt2x00soc.h"
-#if IS_ENABLED(CONFIG_MTD)
static void rt2800lib_eeprom_swap(struct rt2x00_dev *rt2x00dev)
{
struct device_node *np = rt2x00dev->dev->of_node;
-@@ -33,6 +33,7 @@ static void rt2800lib_eeprom_swap(struct
+@@ -32,6 +32,7 @@ static void rt2800lib_eeprom_swap(struct
rt2x00dev->eeprom[i] = swab16(rt2x00dev->eeprom[i]);
}
static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev)
{
struct device_node *np = rt2x00dev->dev->of_node, *mtd_np = NULL;
-@@ -86,6 +87,40 @@ static int rt2800lib_read_eeprom_mtd(str
+@@ -85,6 +86,40 @@ static int rt2800lib_read_eeprom_mtd(str
}
#endif
static const char *
rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
{
-@@ -153,6 +188,10 @@ int rt2x00lib_read_eeprom(struct rt2x00_
+@@ -152,6 +187,10 @@ int rt2x00lib_read_eeprom(struct rt2x00_
return 0;
#endif
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
-@@ -33,6 +33,27 @@ static void rt2800lib_eeprom_swap(struct
+@@ -32,6 +32,27 @@ static void rt2800lib_eeprom_swap(struct
rt2x00dev->eeprom[i] = swab16(rt2x00dev->eeprom[i]);
}
#if IS_ENABLED(CONFIG_MTD)
static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev)
{
-@@ -182,6 +203,10 @@ int rt2x00lib_read_eeprom(struct rt2x00_
+@@ -181,6 +202,10 @@ int rt2x00lib_read_eeprom(struct rt2x00_
{
int ret;
+++ /dev/null
-From 04dbd87265f6ba4a373b211ba324b437d224fb2d Mon Sep 17 00:00:00 2001
-Date: Sun, 17 Mar 2013 00:03:31 +0100
-Subject: [PATCH 21/38] rt2x00: make wmac loadable via OF on rt288x/305x SoC
-
-This patch ads the match table to allow loading the wmac support from a
-devicetree.
-
----
- drivers/net/wireless/ralink/rt2x00/rt2800pci.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
-@@ -237,10 +237,18 @@ static int bp_rt2x00soc_remove(struct pl
- return 0;
- }
- #endif
-+
-+static const struct of_device_id rt2880_wmac_match[] = {
-+ { .compatible = "ralink,rt2880-wmac" },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, rt2880_wmac_match);
-+
- static struct platform_driver rt2800soc_driver = {
- .driver = {
- .name = "rt2800_wmac",
- .mod_name = KBUILD_MODNAME,
-+ .of_match_table = rt2880_wmac_match,
- },
- .probe = rt2800soc_probe,
- #if LINUX_VERSION_IS_GEQ(6,11,0)
---
.../net/wireless/ralink/rt2x00/rt2800lib.c | 58 +++++++++++++++++++
drivers/net/wireless/ralink/rt2x00/rt2x00.h | 5 ++
- .../net/wireless/ralink/rt2x00/rt2x00soc.c | 15 +++++
+ .../net/wireless/ralink/rt2x00/rt2800soc.c | 15 +++++
3 files changed, 78 insertions(+)
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
};
struct rt2x00_bar_list_entry {
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c
-@@ -97,6 +97,21 @@ int rt2x00soc_probe(struct platform_devi
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
+@@ -298,6 +298,21 @@ static int rt2x00soc_probe(struct platfo
if (retval)
- goto exit_free_reg;
+ goto exit_free_device;
+ rt2x00dev->pinctrl = devm_pinctrl_get(&pdev->dev);
+ if (IS_ERR(rt2x00dev->pinctrl)) {
+
return 0;
- exit_free_reg:
+ exit_free_device:
/* Allow hardware encryption to be disabled. */
static bool modparam_nohwcrypt;
module_param_named(nohwcrypt, modparam_nohwcrypt, bool, 0444);
-@@ -118,6 +124,27 @@ static int rt2800soc_write_firmware(stru
- return 0;
+@@ -136,6 +142,27 @@ static int rt2800soc_resume(struct platf
}
+ #endif /* CONFIG_PM */
+#ifdef CONFIG_SOC_MT7620
+static int rt2800soc_get_chippkg(void)
static const struct ieee80211_ops rt2800soc_mac80211_ops = {
.add_chanctx = ieee80211_emulate_add_chanctx,
.remove_chanctx = ieee80211_emulate_remove_chanctx,
-@@ -165,6 +192,9 @@ static const struct rt2800_ops rt2800soc
+@@ -183,6 +210,9 @@ static const struct rt2800_ops rt2800soc
.drv_init_registers = rt2800mmio_init_registers,
.drv_get_txwi = rt2800mmio_get_txwi,
.drv_get_dma_done = rt2800mmio_get_dma_done,
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
-@@ -1691,12 +1691,6 @@ static int ieee80211_stop_ap(struct wiph
+@@ -1882,12 +1882,6 @@ static int ieee80211_stop_ap(struct wiph
__sta_info_flush(sdata, true, link_id, NULL);
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
-@@ -1595,24 +1595,6 @@ int ieee80211_register_hw(struct ieee802
+@@ -1597,24 +1597,6 @@ int ieee80211_register_hw(struct ieee802
ieee80211_check_wbrf_support(local);
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
-@@ -2925,6 +2925,8 @@ static int ieee80211_scan(struct wiphy *
+@@ -3131,6 +3131,8 @@ static int ieee80211_scan(struct wiphy *
*/
fallthrough;
case NL80211_IFTYPE_AP:
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
-@@ -2468,6 +2468,13 @@ static void sta_stats_decode_rate(struct
+@@ -2526,6 +2526,13 @@ static void sta_stats_decode_rate(struct
sband = local->hw.wiphy->bands[band];
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
-@@ -582,6 +582,7 @@ __sta_info_alloc(struct ieee80211_sub_if
+@@ -630,6 +630,7 @@ __sta_info_alloc(struct ieee80211_sub_if
spin_lock_init(&sta->ps_lock);
INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames);
wiphy_work_init(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
-@@ -103,6 +103,8 @@ ieee80211_sta_keep_active(struct sta_inf
+@@ -111,6 +111,8 @@ ieee80211_sta_keep_active(struct sta_inf
return time_before_eq(jiffies, sta->airtime[ac].last_active + HZ / 10);
}
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
-@@ -4066,7 +4066,7 @@ struct ieee80211_txq *ieee80211_next_txq
+@@ -4084,7 +4084,7 @@ struct ieee80211_txq *ieee80211_next_txq
if (deficit < 0)
sta->airtime[txqi->txq.ac].deficit +=
if (deficit < 0 || !aql_check) {
list_move_tail(&txqi->schedule_order,
-@@ -4209,7 +4209,8 @@ bool ieee80211_txq_may_transmit(struct i
+@@ -4229,7 +4229,8 @@ bool ieee80211_txq_may_transmit(struct i
}
sta = container_of(iter->txq.sta, struct sta_info, sta);
if (ieee80211_sta_deficit(sta, ac) < 0)
list_move_tail(&iter->schedule_order, &local->active_txqs[ac]);
}
-@@ -4217,7 +4218,7 @@ bool ieee80211_txq_may_transmit(struct i
+@@ -4237,7 +4238,7 @@ bool ieee80211_txq_may_transmit(struct i
if (sta->airtime[ac].deficit >= 0)
goto out;
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
-@@ -190,6 +190,8 @@ enum ieee80211_channel_flags {
+@@ -187,6 +187,8 @@ enum ieee80211_channel_flags {
* @dfs_state: current state of this channel. Only relevant if radar is required
* on this channel.
* @dfs_state_entered: timestamp (jiffies) when the dfs state was entered.
* @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels.
* @psd: power spectral density (in dBm)
*/
-@@ -207,6 +209,7 @@ struct ieee80211_channel {
+@@ -204,6 +206,7 @@ struct ieee80211_channel {
int orig_mag, orig_mpwr;
enum nl80211_dfs_state dfs_state;
unsigned long dfs_state_entered;
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
-@@ -643,6 +643,8 @@ void cfg80211_set_dfs_state(struct wiphy
+@@ -639,6 +639,8 @@ void cfg80211_set_dfs_state(struct wiphy
c->dfs_state = dfs_state;
c->dfs_state_entered = jiffies;
{
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
-@@ -474,6 +474,8 @@ void cfg80211_set_dfs_state(struct wiphy
+@@ -481,6 +481,8 @@ void cfg80211_set_dfs_state(struct wiphy
enum nl80211_dfs_state dfs_state);
void cfg80211_dfs_channels_update_work(struct work_struct *work);
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
-@@ -1038,6 +1038,8 @@ void cfg80211_dfs_channels_update_work(s
+@@ -1056,6 +1056,8 @@ void cfg80211_dfs_channels_update_work(s
if (c->dfs_state == NL80211_DFS_UNAVAILABLE) {
time_dfs_update = IEEE80211_DFS_MIN_NOP_TIME_MS;
radar_event = NL80211_RADAR_NOP_FINISHED;
} else {
if (regulatory_pre_cac_allowed(wiphy) ||
cfg80211_any_wiphy_oper_chan(wiphy, c))
-@@ -1045,11 +1047,10 @@ void cfg80211_dfs_channels_update_work(s
+@@ -1063,11 +1065,10 @@ void cfg80211_dfs_channels_update_work(s
time_dfs_update = REG_PRE_CAC_EXPIRY_GRACE_MS;
radar_event = NL80211_RADAR_PRE_CAC_EXPIRED;
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
-@@ -3437,6 +3437,7 @@ enum wiphy_params_flags {
+@@ -3604,6 +3604,7 @@ enum wiphy_params_flags {
/* The per TXQ device queue limit in airtime */
#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L 5000
#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H 12000
#define IEEE80211_AQL_THRESHOLD 24000
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
-@@ -215,11 +215,13 @@ static ssize_t aql_pending_read(struct f
+@@ -213,11 +213,13 @@ static ssize_t aql_pending_read(struct f
"VI %u us\n"
"BE %u us\n"
"BK %u us\n"
atomic_read(&local->aql_total_pending_airtime));
return simple_read_from_buffer(user_buf, count, ppos,
buf, len);
-@@ -245,7 +247,8 @@ static ssize_t aql_txq_limit_read(struct
+@@ -243,7 +245,8 @@ static ssize_t aql_txq_limit_read(struct
"VO %u %u\n"
"VI %u %u\n"
"BE %u %u\n"
local->aql_txq_limit_low[IEEE80211_AC_VO],
local->aql_txq_limit_high[IEEE80211_AC_VO],
local->aql_txq_limit_low[IEEE80211_AC_VI],
-@@ -253,7 +256,8 @@ static ssize_t aql_txq_limit_read(struct
+@@ -251,7 +254,8 @@ static ssize_t aql_txq_limit_read(struct
local->aql_txq_limit_low[IEEE80211_AC_BE],
local->aql_txq_limit_high[IEEE80211_AC_BE],
local->aql_txq_limit_low[IEEE80211_AC_BK],
return simple_read_from_buffer(user_buf, count, ppos,
buf, len);
}
-@@ -279,6 +283,11 @@ static ssize_t aql_txq_limit_write(struc
+@@ -277,6 +281,11 @@ static ssize_t aql_txq_limit_write(struc
else
buf[count] = '\0';
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
-@@ -1377,10 +1377,12 @@ struct ieee80211_local {
+@@ -1428,10 +1428,12 @@ struct ieee80211_local {
spinlock_t handle_wake_tx_queue_lock;
u16 airtime_flags;
const struct ieee80211_ops *ops;
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
-@@ -959,6 +959,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
+@@ -984,6 +984,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
spin_lock_init(&local->rx_path_lock);
spin_lock_init(&local->queue_stop_reason_lock);
spin_lock_init(&local->active_txq_lock[i]);
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
-@@ -2382,13 +2382,28 @@ EXPORT_SYMBOL(ieee80211_sta_recalc_aggre
+@@ -2431,13 +2431,28 @@ EXPORT_SYMBOL(ieee80211_sta_recalc_aggre
void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
struct sta_info *sta, u8 ac,
atomic_add(tx_airtime,
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
-@@ -2539,7 +2539,7 @@ static u16 ieee80211_store_ack_skb(struc
+@@ -2554,7 +2554,7 @@ static u16 ieee80211_store_ack_skb(struc
spin_lock_irqsave(&local->ack_status_lock, flags);
id = idr_alloc(&local->ack_status_frames, ack_skb,
spin_unlock_irqrestore(&local->ack_status_lock, flags);
if (id >= 0) {
-@@ -3967,20 +3967,20 @@ begin:
+@@ -3985,20 +3985,20 @@ begin:
encap_out:
info->control.vif = vif;
}
return skb;
-@@ -4032,6 +4032,7 @@ struct ieee80211_txq *ieee80211_next_txq
+@@ -4050,6 +4050,7 @@ struct ieee80211_txq *ieee80211_next_txq
struct ieee80211_txq *ret = NULL;
struct txq_info *txqi = NULL, *head = NULL;
bool found_eligible_txq = false;
spin_lock_bh(&local->active_txq_lock[ac]);
-@@ -4055,26 +4056,26 @@ struct ieee80211_txq *ieee80211_next_txq
+@@ -4073,26 +4074,26 @@ struct ieee80211_txq *ieee80211_next_txq
if (!head)
head = txqi;
if (txqi->schedule_round == local->schedule_round[ac])
goto out;
-@@ -4139,7 +4140,8 @@ bool ieee80211_txq_airtime_check(struct
+@@ -4159,7 +4160,8 @@ bool ieee80211_txq_airtime_check(struct
return true;
if (!txq->sta)
if (unlikely(txq->tid == IEEE80211_NUM_TIDS))
return true;
-@@ -4188,15 +4190,15 @@ bool ieee80211_txq_may_transmit(struct i
+@@ -4208,15 +4210,15 @@ bool ieee80211_txq_may_transmit(struct i
spin_lock_bh(&local->active_txq_lock[ac]);
if (iter == txqi)
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
-@@ -1245,8 +1245,8 @@ struct ieee80211_tx_info {
+@@ -1249,8 +1249,8 @@ struct ieee80211_tx_info {
status_data_idr:1,
status_data:13,
hw_queue:4,
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
-@@ -734,7 +734,7 @@ static void ieee80211_report_used_skb(st
+@@ -751,7 +751,7 @@ static void ieee80211_report_used_skb(st
ieee80211_sta_update_pending_airtime(local, sta,
skb_get_queue_mapping(skb),
tx_time_est,
rcu_read_unlock();
}
-@@ -1143,10 +1143,11 @@ void ieee80211_tx_status_ext(struct ieee
+@@ -1160,10 +1160,11 @@ void ieee80211_tx_status_ext(struct ieee
/* Do this here to avoid the expensive lookup of the sta
* in ieee80211_report_used_skb().
*/
+++ /dev/null
-Date: Thu, 17 Jul 2025 18:25:46 +0200
-Subject: [PATCH] wifi: mac80211: Do not schedule stopped TXQs
-
-Ignore TXQs with the flag IEEE80211_TXQ_STOP when scheduling a queue.
-
-The flag is only set after all fragments have been dequeued and won't
-allow dequeueing other frames as long as the flag is set.
-
-For drivers using ieee80211_txq_schedule_start() this prevents an
-loop trying to push the queued frames while IEEE80211_TXQ_STOP is set:
-
-After setting IEEE80211_TXQ_STOP the driver will call
-ieee80211_return_txq(). Which calls __ieee80211_schedule_txq(), detects
-that there sill are frames in the queue and immediately restarts the
-stopped TXQ. Which can't dequeue any frame and thus starts over the loop.
-
-Fixes: ba8c3d6f16a1 ("mac80211: add an intermediate software queue implementation")
----
-
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -4099,7 +4099,9 @@ void __ieee80211_schedule_txq(struct iee
-
- spin_lock_bh(&local->active_txq_lock[txq->ac]);
-
-- has_queue = force || txq_has_queue(txq);
-+ has_queue = force ||
-+ (!test_bit(IEEE80211_TXQ_STOP, &txqi->flags) &&
-+ txq_has_queue(txq));
- if (list_empty(&txqi->schedule_order) &&
- (has_queue || ieee80211_txq_keep_active(txqi))) {
- /* If airtime accounting is active, always enqueue STAs at the
+++ /dev/null
-Date: Thu, 17 Jul 2025 18:25:47 +0200
-Subject: [PATCH] wifi: mac80211: Don't call fq_flow_idx() for management
- frames
-
-skb_get_hash() can only be used when the skb is linked to a netdev
-device.
-
-Fixes: 73bc9e0af594 ("mac80211: don't apply flow control on management frames")
----
-
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -1428,7 +1428,7 @@ static void ieee80211_txq_enqueue(struct
- {
- struct fq *fq = &local->fq;
- struct fq_tin *tin = &txqi->tin;
-- u32 flow_idx = fq_flow_idx(fq, skb);
-+ u32 flow_idx;
-
- ieee80211_set_skb_enqueue_time(skb);
-
-@@ -1444,6 +1444,7 @@ static void ieee80211_txq_enqueue(struct
- IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
- __skb_queue_tail(&txqi->frags, skb);
- } else {
-+ flow_idx = fq_flow_idx(fq, skb);
- fq_tin_enqueue(fq, tin, flow_idx, skb,
- fq_skb_free_func);
- }
+++ /dev/null
-Date: Thu, 17 Jul 2025 17:45:28 +0200
-Subject: [PATCH] wifi: mac80211: Check 802.11 encaps offloading in
- ieee80211_tx_h_select_key()
-
-With 802.11 encapsulation offloading, ieee80211_tx_h_select_key() is
-called on 802.3 frames. In that case do not try to use skb data as
-valid 802.11 headers.
-
-Fixes: bb42f2d13ffc ("mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue")
-Link: https://patch.msgid.link/1af4b5b903a5fca5ebe67333d5854f93b2be5abe.1752765971.git.repk@triplefau.lt
----
-
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -612,6 +612,12 @@ ieee80211_tx_h_select_key(struct ieee802
- else
- tx->key = NULL;
-
-+ if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
-+ if (tx->key && tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
-+ info->control.hw_key = &tx->key->conf;
-+ return TX_CONTINUE;
-+ }
-+
- if (tx->key) {
- bool skip_hw = false;
-
+++ /dev/null
-Date: Thu, 17 Jul 2025 17:45:29 +0200
-Subject: [PATCH] Reapply "wifi: mac80211: Update skb's control block key in
- ieee80211_tx_dequeue()"
-
-This reverts commit 0937cb5f345c ("Revert "wifi: mac80211: Update
-skb's control block key in ieee80211_tx_dequeue()"").
-
-This commit broke TX with 802.11 encapsulation HW offloading, now that
-this is fixed, reapply it.
-
-Fixes: bb42f2d13ffc ("mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue")
-Link: https://patch.msgid.link/66b8fc39fb0194fa06c9ca7eeb6ffe0118dcb3ec.1752765971.git.repk@triplefau.lt
----
-
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -3883,6 +3883,7 @@ begin:
- * The key can be removed while the packet was queued, so need to call
- * this here to get the current key.
- */
-+ info->control.hw_key = NULL;
- r = ieee80211_tx_h_select_key(&tx);
- if (r != TX_CONTINUE) {
- ieee80211_free_txskb(&local->hw, skb);
+++ /dev/null
-Date: Fri, 18 Jul 2025 11:38:35 +0530
-Subject: [PATCH] wifi: mac80211: Add link iteration macro for link data
- with rcu_dereference
-
-Currently, the existing macro for_each_link_data() uses sdata_dereference()
-which requires the wiphy lock. This lock cannot be used in atomic or RCU
-read-side contexts, such as in the RX path.
-
-Introduce a new macro, for_each_link_data_rcu(), that iterates over link of
-sdata using rcu_dereference(), making it safe to use in RCU contexts. This
-allows callers to access link data without requiring the wiphy lock.
-
-The macro takes into account the vif.valid_links bitmap and ensures only
-valid links are accessed safely. Callers are responsible for ensuring that
-rcu_read_lock() is held when using this macro.
-
----
-
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -1237,6 +1237,19 @@ struct ieee80211_sub_if_data *vif_to_sda
- ((__link) = sdata_dereference((__sdata)->link[__link_id], \
- (__sdata))))
-
-+/*
-+ * for_each_link_data_rcu should be used under RCU read lock.
-+ */
-+#define for_each_link_data_rcu(sdata, __link) \
-+ /* outer loop just to define the variable ... */ \
-+ for (struct ieee80211_sub_if_data *__sdata = (sdata); __sdata; \
-+ __sdata = NULL /* always stop */) \
-+ for (int __link_id = 0; \
-+ __link_id < ARRAY_SIZE((__sdata)->link); __link_id++) \
-+ if ((!(__sdata)->vif.valid_links || \
-+ (__sdata)->vif.valid_links & BIT(__link_id)) && \
-+ ((__link) = rcu_dereference((__sdata)->link[__link_id]))) \
-+
- static inline int
- ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems,
- struct cfg80211_rnr_elems *rnr_elems,
+++ /dev/null
-Date: Fri, 18 Jul 2025 11:38:36 +0530
-Subject: [PATCH] wifi: mac80211: extend beacon monitoring for MLO
-
-Currently, reset beacon monitor (ieee80211_sta_reset_beacon_monitor())
-timer is handled only for non-AP non-MLD STA and do not support non-AP MLD
-STA. When the beacon loss occurs in non-AP MLD STA with the current
-implementation, it is treated as a single link and the timer will reset
-based on the timeout of the deflink, without checking all the links.
-
-Check the CSA flags for all the links in the MLO and decide whether to
-schedule the work queue for beacon loss. If any of the links has CSA
-active, then beacon loss work is not scheduled.
-
-Also, call the functions ieee80211_sta_reset_beacon_monitor() and
-ieee80211_sta_reset_conn_monitor() from ieee80211_csa_switch_work() only
-when all the links are CSA active.
-
----
-
---- a/net/mac80211/mlme.c
-+++ b/net/mac80211/mlme.c
-@@ -2439,6 +2439,21 @@ static void ieee80211_csa_switch_work(st
- }
- }
-
-+ /*
-+ * It is not necessary to reset these timers if any link does not
-+ * have an active CSA and that link still receives the beacons
-+ * when other links have active CSA.
-+ */
-+ for_each_link_data(sdata, link) {
-+ if (!link->conf->csa_active)
-+ return;
-+ }
-+
-+ /*
-+ * Reset the beacon monitor and connection monitor timers when CSA
-+ * is active for all links in MLO when channel switch occurs in all
-+ * the links.
-+ */
- ieee80211_sta_reset_beacon_monitor(sdata);
- ieee80211_sta_reset_conn_monitor(sdata);
- }
-@@ -8389,16 +8404,32 @@ void ieee80211_sta_work(struct ieee80211
- }
- }
-
-+static bool
-+ieee80211_is_csa_in_progress(struct ieee80211_sub_if_data *sdata)
-+{
-+ /*
-+ * In MLO, check the CSA flags 'active' and 'waiting_bcn' for all
-+ * the links.
-+ */
-+ struct ieee80211_link_data *link;
-+
-+ guard(rcu)();
-+
-+ for_each_link_data_rcu(sdata, link) {
-+ if (!(link->conf->csa_active &&
-+ !link->u.mgd.csa.waiting_bcn))
-+ return false;
-+ }
-+
-+ return true;
-+}
-+
- static void ieee80211_sta_bcn_mon_timer(struct timer_list *t)
- {
- struct ieee80211_sub_if_data *sdata =
- timer_container_of(sdata, t, u.mgd.bcn_mon_timer);
-
-- if (WARN_ON(ieee80211_vif_is_mld(&sdata->vif)))
-- return;
--
-- if (sdata->vif.bss_conf.csa_active &&
-- !sdata->deflink.u.mgd.csa.waiting_bcn)
-+ if (ieee80211_is_csa_in_progress(sdata))
- return;
-
- if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)
+++ /dev/null
-Date: Fri, 18 Jul 2025 11:38:37 +0530
-Subject: [PATCH] wifi: mac80211: extend connection monitoring for MLO
-
-Currently, reset connection monitor (ieee80211_sta_reset_conn_monitor())
-timer is handled only for non-AP non-MLD STA and do not support non-AP MLD
-STA. The current implementation checks for the CSA active and update the
-monitor timer with the timeout value of deflink and reset the timer based
-on the deflink's timeout value else schedule the connection loss work when
-the deflink is timed out and it won't work for the non-AP MLD STA.
-
-Handle the reset connection monitor timer for non-AP MLD STA by updating
-the monitor timer with the timeout value which is determined based on the
-link that will expire last among all the links in MLO. If at least one link
-has not timed out, the timer is updated accordingly with the latest timeout
-value else schedule the connection loss work when all links have timed out.
-
-Remove the MLO-related WARN_ON() checks in the beacon and connection
-monitoring logic code paths as they support MLO now.
-
----
-
---- a/net/mac80211/mlme.c
-+++ b/net/mac80211/mlme.c
-@@ -4300,9 +4300,6 @@ static void ieee80211_mgd_probe_ap_send(
-
- lockdep_assert_wiphy(sdata->local->hw.wiphy);
-
-- if (WARN_ON(ieee80211_vif_is_mld(&sdata->vif)))
-- return;
--
- /*
- * Try sending broadcast probe requests for the last three
- * probe requests after the first ones failed since some
-@@ -4348,9 +4345,6 @@ static void ieee80211_mgd_probe_ap(struc
-
- lockdep_assert_wiphy(sdata->local->hw.wiphy);
-
-- if (WARN_ON_ONCE(ieee80211_vif_is_mld(&sdata->vif)))
-- return;
--
- if (!ieee80211_sdata_running(sdata))
- return;
-
-@@ -8440,36 +8434,70 @@ static void ieee80211_sta_bcn_mon_timer(
- &sdata->u.mgd.beacon_connection_loss_work);
- }
-
-+static unsigned long
-+ieee80211_latest_active_link_conn_timeout(struct ieee80211_sub_if_data *sdata)
-+{
-+ unsigned long latest_timeout;
-+ unsigned int link_id;
-+ struct sta_info *sta;
-+
-+ guard(rcu)();
-+
-+ sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr);
-+ if (!sta)
-+ return 0;
-+
-+ for (link_id = 0; link_id < ARRAY_SIZE(sta->link);
-+ link_id++) {
-+ struct link_sta_info *link_sta;
-+ unsigned long timeout;
-+
-+ link_sta = rcu_dereference(sta->link[link_id]);
-+ if (!link_sta)
-+ continue;
-+
-+ timeout = link_sta->status_stats.last_ack;
-+ if (time_before(timeout, link_sta->rx_stats.last_rx))
-+ timeout = link_sta->rx_stats.last_rx;
-+
-+ timeout += IEEE80211_CONNECTION_IDLE_TIME;
-+
-+ /*
-+ * latest_timeout holds the timeout of the link
-+ * that will expire last among all links in an
-+ * non-AP MLD STA. This ensures that the connection
-+ * monitor timer is only reset if at least one link
-+ * is still active, and it is scheduled to fire at
-+ * the latest possible timeout.
-+ */
-+ if (time_is_after_jiffies(timeout) &&
-+ time_after(timeout, latest_timeout))
-+ latest_timeout = timeout;
-+ }
-+
-+ return latest_timeout;
-+}
-+
- static void ieee80211_sta_conn_mon_timer(struct timer_list *t)
- {
- struct ieee80211_sub_if_data *sdata =
- timer_container_of(sdata, t, u.mgd.conn_mon_timer);
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct ieee80211_local *local = sdata->local;
-- struct sta_info *sta;
-- unsigned long timeout;
-+ unsigned long latest_timeout;
-
-- if (WARN_ON(ieee80211_vif_is_mld(&sdata->vif)))
-- return;
--
-- if (sdata->vif.bss_conf.csa_active &&
-- !sdata->deflink.u.mgd.csa.waiting_bcn)
-- return;
--
-- sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr);
-- if (!sta)
-+ if (ieee80211_is_csa_in_progress(sdata))
- return;
-
-- timeout = sta->deflink.status_stats.last_ack;
-- if (time_before(sta->deflink.status_stats.last_ack, sta->deflink.rx_stats.last_rx))
-- timeout = sta->deflink.rx_stats.last_rx;
-- timeout += IEEE80211_CONNECTION_IDLE_TIME;
-+ latest_timeout = ieee80211_latest_active_link_conn_timeout(sdata);
-
-- /* If timeout is after now, then update timer to fire at
-+ /*
-+ * If latest timeout is after now, then update timer to fire at
- * the later date, but do not actually probe at this time.
- */
-- if (time_is_after_jiffies(timeout)) {
-- mod_timer(&ifmgd->conn_mon_timer, round_jiffies_up(timeout));
-+ if (latest_timeout) {
-+ mod_timer(&ifmgd->conn_mon_timer,
-+ round_jiffies_up(latest_timeout));
- return;
- }
-
+++ /dev/null
-Date: Tue, 26 Aug 2025 13:54:31 +0200
-Subject: [PATCH] wifi: mac80211: Make CONNECTION_MONITOR optional for MLO sta
-
-Since commit '1bc892d76a6f ("wifi: mac80211: extend connection
-monitoring for MLO")' mac80211 supports connection monitor for MLO
-client interfaces. Remove the CONNECTION_MONITOR requirement in
-ieee80211_register_hw routine.
-
-Fixes: 1bc892d76a6f ("wifi: mac80211: extend connection monitoring for MLO")
----
-
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -1179,9 +1179,6 @@ int ieee80211_register_hw(struct ieee802
- if (WARN_ON(!ieee80211_hw_check(hw, MFP_CAPABLE)))
- return -EINVAL;
-
-- if (WARN_ON(!ieee80211_hw_check(hw, CONNECTION_MONITOR)))
-- return -EINVAL;
--
- if (WARN_ON(ieee80211_hw_check(hw, NEED_DTIM_BEFORE_ASSOC)))
- return -EINVAL;
-
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
-@@ -3559,6 +3559,27 @@ static int ieee80211_set_bitrate_mask(st
- return 0;
+@@ -3825,6 +3825,27 @@ static bool ieee80211_is_scan_ongoing(st
+ return false;
}
+bool ieee80211_scanning_busy(struct ieee80211_local *local,
+ struct wiphy *wiphy = local->hw.wiphy;
+ u32 mask;
+
-+ if (list_empty(&local->roc_list) && !local->scanning)
++ if (!ieee80211_is_scan_ongoing(wiphy, local, chandef))
+ return false;
+
+ if (!wiphy->n_radio)
static int ieee80211_start_radar_detection(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_chan_def *chandef,
-@@ -3572,7 +3593,7 @@ static int ieee80211_start_radar_detecti
+@@ -3838,7 +3859,7 @@ static int ieee80211_start_radar_detecti
lockdep_assert_wiphy(local->hw.wiphy);
-- if (!list_empty(&local->roc_list) || local->scanning)
+- if (ieee80211_is_scan_ongoing(wiphy, local, chandef))
+ if (ieee80211_scanning_busy(local, chandef))
return -EBUSY;
link_data = sdata_dereference(sdata->link[link_id], sdata);
-@@ -4064,7 +4085,7 @@ __ieee80211_channel_switch(struct wiphy
+@@ -4330,7 +4351,7 @@ __ieee80211_channel_switch(struct wiphy
lockdep_assert_wiphy(local->hw.wiphy);
-- if (!list_empty(&local->roc_list) || local->scanning)
+- if (ieee80211_is_scan_ongoing(wiphy, local, ¶ms->chandef))
+ if (ieee80211_scanning_busy(local, ¶ms->chandef))
return -EBUSY;
if (sdata->wdev.links[link_id].cac_started)
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
-@@ -644,14 +644,24 @@ ieee80211_find_chanctx(struct ieee80211_
+@@ -644,10 +644,11 @@ ieee80211_find_chanctx(struct ieee80211_
return NULL;
}
--bool ieee80211_is_radar_required(struct ieee80211_local *local)
-+bool ieee80211_is_radar_required(struct ieee80211_local *local, u32 radio_mask)
+-bool ieee80211_is_radar_required(struct ieee80211_local *local,
++bool ieee80211_is_radar_required(struct ieee80211_local *local, u32 radio_mask,
+ struct cfg80211_scan_request *req)
{
+ struct wiphy *wiphy = local->hw.wiphy;
+ struct ieee80211_chanctx_conf *conf;
struct ieee80211_link_data *link;
-
- lockdep_assert_wiphy(local->hw.wiphy);
+ struct ieee80211_channel *chan;
+ int radio_idx;
+@@ -658,14 +659,25 @@ bool ieee80211_is_radar_required(struct
+ return false;
for_each_sdata_link(local, link) {
-- if (link->radar_required)
+- if (link->radar_required) {
+- chan = link->conf->chanreq.oper.chan;
+- radio_idx = cfg80211_get_radio_idx_by_chan(wiphy, chan);
+-
+- if (ieee80211_is_radio_idx_in_scan_req(wiphy, req,
+- radio_idx))
+- return true;
+- }
+ if (!link->radar_required)
+ continue;
++
++ chan = link->conf->chanreq.oper.chan;
++ radio_idx = cfg80211_get_radio_idx_by_chan(wiphy, chan);
++
++ if (ieee80211_is_radio_idx_in_scan_req(wiphy, req,
++ radio_idx))
++ return true;
++
+ if (!local->hw.wiphy->n_radio)
+ return true;
+
+ continue;
+
+ if (conf->radio_idx >= 0 && (radio_mask & BIT(conf->radio_idx)))
- return true;
++ return true;
}
+ return false;
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
-@@ -1988,6 +1988,12 @@ int ieee80211_mesh_finish_csa(struct iee
+@@ -2022,6 +2022,13 @@ int ieee80211_mesh_finish_csa(struct iee
u64 *changed);
/* scan/BSS handling */
+bool ieee80211_scanning_busy(struct ieee80211_local *local,
+ struct cfg80211_chan_def *chandef);
+u32 ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata,
++ struct cfg80211_scan_request *req,
+ u32 radio_mask);
void ieee80211_scan_work(struct wiphy *wiphy, struct wiphy_work *work);
int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
const u8 *ssid, u8 ssid_len,
-@@ -2026,6 +2032,7 @@ void ieee80211_sched_scan_stopped_work(s
+@@ -2060,6 +2067,7 @@ void ieee80211_sched_scan_stopped_work(s
/* off-channel/mgmt-tx */
void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local);
void ieee80211_offchannel_return(struct ieee80211_local *local);
void ieee80211_roc_setup(struct ieee80211_local *local);
void ieee80211_start_next_roc(struct ieee80211_local *local);
void ieee80211_reconfig_roc(struct ieee80211_local *local);
-@@ -2673,6 +2680,8 @@ bool ieee80211_chandef_s1g_oper(const st
+@@ -2719,6 +2727,8 @@ bool ieee80211_chandef_s1g_oper(struct i
struct cfg80211_chan_def *chandef);
void ieee80211_chandef_downgrade(struct cfg80211_chan_def *chandef,
struct ieee80211_conn_settings *conn);
static inline void
ieee80211_chanreq_downgrade(struct ieee80211_chan_req *chanreq,
struct ieee80211_conn_settings *conn)
-@@ -2729,7 +2738,7 @@ void ieee80211_recalc_chanctx_min_def(st
+@@ -2775,7 +2785,7 @@ void ieee80211_recalc_chanctx_min_def(st
struct ieee80211_chanctx *ctx,
struct ieee80211_link_data *rsvd_for,
bool check_reserved);
--bool ieee80211_is_radar_required(struct ieee80211_local *local);
-+bool ieee80211_is_radar_required(struct ieee80211_local *local, u32 radio_mask);
-
- void ieee80211_dfs_cac_timer_work(struct wiphy *wiphy, struct wiphy_work *work);
- void ieee80211_dfs_cac_cancel(struct ieee80211_local *local,
+-bool ieee80211_is_radar_required(struct ieee80211_local *local,
++bool ieee80211_is_radar_required(struct ieee80211_local *local, u32 radio_mask,
+ struct cfg80211_scan_request *req);
+ bool ieee80211_is_radio_idx_in_scan_req(struct wiphy *wiphy,
+ struct cfg80211_scan_request *scan_req,
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -168,6 +168,35 @@ void ieee80211_offchannel_return(struct
static void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
{
/* was never transmitted */
-@@ -566,7 +595,9 @@ static int ieee80211_start_roc_work(stru
+@@ -566,8 +595,10 @@ static int ieee80211_start_roc_work(stru
enum ieee80211_roc_type type)
{
struct ieee80211_roc_work *roc, *tmp;
+ struct cfg80211_chan_def chandef = {};
bool queued = false, combine_started = true;
+ struct cfg80211_scan_request *req;
+ u32 radio_mask;
int ret;
lockdep_assert_wiphy(local->hw.wiphy);
-@@ -578,6 +609,12 @@ static int ieee80211_start_roc_work(stru
+@@ -579,6 +610,12 @@ static int ieee80211_start_roc_work(stru
if (!local->emulate_chanctx && !local->ops->remain_on_channel)
return -EOPNOTSUPP;
+ cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT);
+ radio_mask = ieee80211_chandef_radio_mask(local, &chandef);
-+ if (!ieee80211_can_leave_ch(sdata, radio_mask) &&
++ if (!ieee80211_can_leave_ch(sdata, req, radio_mask) &&
+ !ieee80211_scanning_busy(local, &chandef))
+ return -EBUSY;
+
roc = kzalloc(sizeof(*roc), GFP_KERNEL);
if (!roc)
return -ENOMEM;
-@@ -613,8 +650,7 @@ static int ieee80211_start_roc_work(stru
- }
+@@ -616,8 +653,7 @@ static int ieee80211_start_roc_work(stru
+ req = wiphy_dereference(local->hw.wiphy, local->scan_req);
/* if there's no need to queue, handle it immediately */
- if (list_empty(&local->roc_list) &&
-- !local->scanning && !ieee80211_is_radar_required(local)) {
+- !local->scanning && !ieee80211_is_radar_required(local, req)) {
+ if (list_empty(&local->roc_list) && !local->scanning) {
/* if not HW assist, just queue & schedule work */
if (!local->ops->remain_on_channel) {
list_add_tail(&roc->list, &local->roc_list);
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
-@@ -586,36 +586,83 @@ static int ieee80211_start_sw_scan(struc
+@@ -586,25 +586,72 @@ static int ieee80211_start_sw_scan(struc
return 0;
}
--static bool __ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata)
+-static bool __ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata,
+- struct cfg80211_scan_request *req)
+u32 ieee80211_scan_req_radio_mask(struct ieee80211_local *local,
+ struct cfg80211_scan_request *req)
+{
+}
+
+u32 ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata,
++ struct cfg80211_scan_request *req,
+ u32 radio_mask)
{
struct ieee80211_local *local = sdata->local;
lockdep_assert_wiphy(local->hw.wiphy);
-- if (!ieee80211_is_radar_required(local))
-+ if (!ieee80211_is_radar_required(local, radio_mask))
+- if (!ieee80211_is_radar_required(local, req))
++ if (!ieee80211_is_radar_required(local, radio_mask, req))
return true;
if (!regulatory_pre_cac_allowed(local->hw.wiphy))
+ continue;
+
+ if (!wiphy->n_radio)
- return false;
++ return false;
+
+ link = sdata_dereference(sdata->link[link_id], sdata);
+ if (!link)
+
+ if (conf->radio_idx >= 0 &&
+ (radio_mask & BIT(conf->radio_idx)))
-+ return false;
+ return false;
+ }
}
return true;
- }
+@@ -612,12 +659,12 @@ static bool __ieee80211_can_leave_ch(str
static bool ieee80211_can_scan(struct ieee80211_local *local,
-- struct ieee80211_sub_if_data *sdata)
-+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_sub_if_data *sdata,
+- struct cfg80211_scan_request *req)
++ struct cfg80211_scan_request *req,
+ u32 radio_mask)
{
-- if (!__ieee80211_can_leave_ch(sdata))
+- if (!__ieee80211_can_leave_ch(sdata, req))
- return false;
-
- if (!list_empty(&local->roc_list))
return false;
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
-@@ -627,15 +674,22 @@ static bool ieee80211_can_scan(struct ie
+@@ -629,19 +676,22 @@ static bool ieee80211_can_scan(struct ie
void ieee80211_run_deferred_scan(struct ieee80211_local *local)
{
+ struct ieee80211_sub_if_data *sdata;
-+ struct cfg80211_scan_request *req;
+ struct cfg80211_scan_request *req;
+ u32 radio_mask;
-+
+
lockdep_assert_wiphy(local->hw.wiphy);
- if (!local->scan_req || local->scanning)
+ req = wiphy_dereference(local->hw.wiphy, local->scan_req);
+ if (!req || local->scanning)
-+ return;
-+
-+ radio_mask = ieee80211_scan_req_radio_mask(local, req);
-+ sdata = wiphy_dereference(local->hw.wiphy, local->scan_sdata);
-+ if (!ieee80211_can_leave_ch(sdata, radio_mask))
return;
+- req = wiphy_dereference(local->hw.wiphy, local->scan_req);
- if (!ieee80211_can_scan(local,
- rcu_dereference_protected(
- local->scan_sdata,
-- lockdep_is_held(&local->hw.wiphy->mtx))))
-+ if (!ieee80211_can_scan(local, sdata, radio_mask))
+- lockdep_is_held(&local->hw.wiphy->mtx)),
+- req))
++ radio_mask = ieee80211_scan_req_radio_mask(local, req);
++ sdata = wiphy_dereference(local->hw.wiphy, local->scan_sdata);
++ if (!ieee80211_can_leave_ch(sdata, req, radio_mask))
++ return;
++
++ if (!ieee80211_can_scan(local, sdata, req, radio_mask))
return;
wiphy_delayed_work_queue(local->hw.wiphy, &local->scan_work,
-@@ -718,6 +772,7 @@ static int __ieee80211_start_scan(struct
+@@ -724,6 +774,7 @@ static int __ieee80211_start_scan(struct
{
struct ieee80211_local *local = sdata->local;
bool hw_scan = local->ops->hw_scan;
int rc;
lockdep_assert_wiphy(local->hw.wiphy);
-@@ -732,10 +787,11 @@ static int __ieee80211_start_scan(struct
+@@ -738,10 +789,11 @@ static int __ieee80211_start_scan(struct
!(sdata->vif.active_links & BIT(req->tsf_report_link_id)))
return -EINVAL;
-- if (!__ieee80211_can_leave_ch(sdata))
+- if (!__ieee80211_can_leave_ch(sdata, req))
+ radio_mask = ieee80211_scan_req_radio_mask(local, req);
-+ if (!ieee80211_can_leave_ch(sdata, radio_mask))
++ if (!ieee80211_can_leave_ch(sdata, req, radio_mask))
return -EBUSY;
-- if (!ieee80211_can_scan(local, sdata)) {
-+ if (!ieee80211_can_scan(local, sdata, radio_mask)) {
+- if (!ieee80211_can_scan(local, sdata, req)) {
++ if (!ieee80211_can_scan(local, sdata, req, radio_mask)) {
/* wait for the work to finish/time out */
rcu_assign_pointer(local->scan_req, req);
rcu_assign_pointer(local->scan_sdata, sdata);
* the suspend->resume cycle. Since we can't check each caller
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
-@@ -2955,6 +2955,9 @@ bool cfg80211_radio_chandef_valid(const
+@@ -2964,6 +2964,9 @@ bool cfg80211_radio_chandef_valid(const
{
u32 freq, width;
+ return false;
+
freq = ieee80211_chandef_to_khz(chandef);
- width = cfg80211_chandef_get_width(chandef);
+ width = MHZ_TO_KHZ(cfg80211_chandef_get_width(chandef));
if (!ieee80211_radio_freq_range_valid(radio, freq, width))
}
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
-@@ -2789,6 +2789,11 @@ u8 *ieee80211_get_bssid(struct ieee80211
+@@ -2839,6 +2839,11 @@ u8 *ieee80211_get_bssid(struct ieee80211
extern const struct ethtool_ops ieee80211_ethtool_ops;
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
-@@ -2648,6 +2648,29 @@ static void sta_set_mesh_sinfo(struct st
+@@ -2977,6 +2977,29 @@ static void sta_set_link_sinfo(struct st
+ }
}
- #endif
+static u32 sta_estimate_expected_throughput(struct sta_info *sta,
+ struct station_info *sinfo)
void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
bool tidstats)
{
-@@ -2871,6 +2894,8 @@ void sta_set_sinfo(struct sta_info *sta,
+@@ -3201,6 +3224,8 @@ void sta_set_sinfo(struct sta_info *sta,
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
thr = sta_get_expected_throughput(sta);
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
-@@ -4320,7 +4320,9 @@ static int ieee80211_probe_client(struct
+@@ -4594,7 +4594,9 @@ static int ieee80211_probe_client(struct
struct ieee80211_tx_info *info;
struct sta_info *sta;
struct ieee80211_chanctx_conf *chanctx_conf;
int ret;
/* the lock is needed to assign the cookie later */
-@@ -4335,7 +4337,23 @@ static int ieee80211_probe_client(struct
+@@ -4609,7 +4611,23 @@ static int ieee80211_probe_client(struct
qos = sta->sta.wme;
if (WARN_ON(!chanctx_conf)) {
ret = -EINVAL;
goto unlock;
-@@ -4367,14 +4385,15 @@ static int ieee80211_probe_client(struct
+@@ -4641,14 +4659,15 @@ static int ieee80211_probe_client(struct
nullfunc->frame_control = fc;
nullfunc->duration_id = 0;
memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN);